1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-04-10 06:27:16 +00:00

Organize Files

This commit is contained in:
Gehstock
2018-10-11 17:43:13 +02:00
parent b8646e9e87
commit 683704ed46
77 changed files with 19520 additions and 0 deletions

30
2048_MiST/2048.qpf Normal file
View File

@@ -0,0 +1,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2010 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
# Version 9.1 Build 350 03/24/2010 Service Pack 2 SJ Web Edition
# Date created = 14:22:39 March 07, 2015
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "9.1"
DATE = "14:22:39 March 07, 2015"
# Revisions
PROJECT_REVISION = "2048"

207
2048_MiST/2048.qsf Normal file
View File

@@ -0,0 +1,207 @@
# -------------------------------------------------------------------------- #
#
# 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 = 16:45:11 February 04, 2018
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# 2048_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 "9.1 SP2"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "14:22:29 MARCH 07, 2015"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name VHDL_FILE rtl/Game.vhd
set_global_assignment -name VHDL_FILE rtl/Game_VIEW.vhd
set_global_assignment -name VHDL_FILE rtl/Game_UTILS.vhd
set_global_assignment -name VHDL_FILE rtl/Game_TYPES.vhd
set_global_assignment -name VHDL_FILE rtl/Game_RANDOMGEN.vhd
set_global_assignment -name VHDL_FILE rtl/Game_KEYBOARD.vhd
set_global_assignment -name VHDL_FILE rtl/Game_GRID_VIEW.vhd
set_global_assignment -name VHDL_FILE rtl/Game_DATA.vhd
set_global_assignment -name VHDL_FILE rtl/Game_CONTROL.vhd
set_global_assignment -name VHDL_FILE rtl/Game_CLKGENERATOR.vhd
set_global_assignment -name VHDL_FILE rtl/Game_CHROM.vhd
set_global_assignment -name VHDL_FILE rtl/Game_CHDISPLAY.vhd
set_global_assignment -name VHDL_FILE rtl/Game_BOX.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
set_global_assignment -name VERILOG_FILE rtl/pll.v
set_global_assignment -name QIP_FILE rtl/pll.qip
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/hq2x.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/game2048_mist.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/scandoubler.sv
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name QIP_FILE rtl/CHAR.qip
# Pin & Location Assignments
# ==========================
set_location_assignment PIN_7 -to LED
set_location_assignment PIN_54 -to CLOCK_27
set_location_assignment PIN_144 -to VGA_R[5]
set_location_assignment PIN_143 -to VGA_R[4]
set_location_assignment PIN_142 -to VGA_R[3]
set_location_assignment PIN_141 -to VGA_R[2]
set_location_assignment PIN_137 -to VGA_R[1]
set_location_assignment PIN_135 -to VGA_R[0]
set_location_assignment PIN_133 -to VGA_B[5]
set_location_assignment PIN_132 -to VGA_B[4]
set_location_assignment PIN_125 -to VGA_B[3]
set_location_assignment PIN_121 -to VGA_B[2]
set_location_assignment PIN_120 -to VGA_B[1]
set_location_assignment PIN_115 -to VGA_B[0]
set_location_assignment PIN_114 -to VGA_G[5]
set_location_assignment PIN_113 -to VGA_G[4]
set_location_assignment PIN_112 -to VGA_G[3]
set_location_assignment PIN_111 -to VGA_G[2]
set_location_assignment PIN_110 -to VGA_G[1]
set_location_assignment PIN_106 -to VGA_G[0]
set_location_assignment PIN_136 -to VGA_VS
set_location_assignment PIN_119 -to VGA_HS
set_location_assignment PIN_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
# Classic Timing Assignments
# ==========================
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name TOP_LEVEL_ENTITY game2048_mist
set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE AREA
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
# Fitter Assignments
# ==================
set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name FITTER_EFFORT "FAST FIT"
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
set_global_assignment -name ENABLE_NCE_PIN OFF
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
# EDA Netlist Writer Assignments
# ==============================
set_global_assignment -name EDA_SIMULATION_TOOL "<None>"
# Assembler Assignments
# =====================
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
set_global_assignment -name GENERATE_RBF_FILE ON
# 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)
# ---------------------------------------
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name EDA_RUN_TOOL_AUTOMATICALLY OFF -section_id eda_simulation
# EDA Netlist Writer Assignments
# ==============================
set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT NONE -section_id eda_simulation
# end EDA_TOOL_SETTINGS(eda_simulation)
# -------------------------------------
# start EDA_TOOL_SETTINGS(eda_palace)
# -----------------------------------
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_palace
# end EDA_TOOL_SETTINGS(eda_palace)
# ---------------------------------
# ------------------
# start ENTITY(Game)
# end ENTITY(Game)
# ----------------
# ---------------------------
# start ENTITY(game2048_mist)
# start LOGICLOCK_REGION(Root Region)
# -----------------------------------
# LogicLock Region Assignments
# ============================
set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region"
set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region"
# end LOGICLOCK_REGION(Root Region)
# ---------------------------------
# start DESIGN_PARTITION(Top)
# ---------------------------
# Incremental Compilation Assignments
# ===================================
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_COLOR 2147039 -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(game2048_mist)
# -------------------------
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

6
2048_MiST/README.txt Normal file
View File

@@ -0,0 +1,6 @@
# 2048-MIST
VHDL implementation of 2048 Game on MiST FPGA Board developed in the "Digital Systems M" course of the University of Bologna
Controls
Arrow Keys

BIN
2048_MiST/Release/2048.rbf Normal file

Binary file not shown.

103
2048_MiST/rtl/2048.sv.bak Normal file
View File

@@ -0,0 +1,103 @@
module gb_mist (
input CLOCK_27,
output LED,
// SPI interface to arm io controller
output SPI_DO,
input SPI_DI,
input SPI_SCK,
input SPI_SS2,
input SPI_SS3,
input SPI_SS4,
input CONF_DATA0,
// video
output VGA_HS,
output VGA_VS,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B
);
assign LED = 1;
`include "rtl/build_id.sv"
localparam CONF_STR = {
"GAMEBOY;;",
"O45,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
"V,v1.00.",`BUILD_DATE
};
wire clk50, clk12p5;
wire ps2_kbd_clk, ps2_kbd_data;
wire [3:0] r, g, b;
wire hs, vs;
wire ypbpr;
wire [31:0] status;
wire [1:0] buttons, switches;
pll pll (
.inclk0(CLOCK_27),
.c0(clk50),
.c1(clk12p5)
);
gb gb (
.clk_50Mhz (clk50 ),
.PS2_CLK (ps2_kbd_clk ),
.PS2_DAT (ps2_kbd_data ),
.hsync (hs ),
.vsync (vs ),
.red (r ),
.green (g ),
.blue (b ),
);
mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io
(
.clk_sys (clk50 ),
.conf_str (CONF_STR ),
.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(1 ),
.ypbpr (ypbpr ),
.ps2_kbd_clk (ps2_kbd_clk ),
.ps2_kbd_data (ps2_kbd_data ),
.status (status )
);
video_mixer #(.LINE_LENGTH(640), .HALF_DEPTH(1)) video_mixer
(
.clk_sys (clk50 ),
.ce_pix (clk12p5 ),
.ce_pix_actual (clk12p5 ),
.SPI_SCK (SPI_SCK ),
.SPI_SS3 (SPI_SS3 ),
.SPI_DI (SPI_DI ),
.R (r ),
.G (g ),
.B (b ),
.HSync (hs ),
.VSync (vs ),
.VGA_R (VGA_R ),
.VGA_G (VGA_G ),
.VGA_B (VGA_B ),
.VGA_VS (VGA_VS ),
.VGA_HS (VGA_HS ),
.scandoubler_disable(1 ),
.scanlines (scandoubler_disable ? 2'b00 : {status[5:4] == 3, status[5:4] == 2}),
.hq2x (status[5:4]==1),
.ypbpr_full (1 ),
.ypbpr (ypbpr ),
.line_start (0 ),
.mono (0 )
);
endmodule

3
2048_MiST/rtl/CHAR.qip Normal file
View File

@@ -0,0 +1,3 @@
set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT"
set_global_assignment -name IP_TOOL_VERSION "13.1"
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "CHAR.vhd"]

143
2048_MiST/rtl/CHAR.vhd Normal file
View File

@@ -0,0 +1,143 @@
-- megafunction wizard: %ROM: 1-PORT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- ============================================================
-- File Name: CHAR.vhd
-- Megafunction Name(s):
-- altsyncram
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.1.0 Build 162 10/23/2013 SJ Web Edition
-- ************************************************************
--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.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
ENTITY CHAR IS
PORT
(
address : IN STD_LOGIC_VECTOR (6 DOWNTO 0);
clock : IN STD_LOGIC := '1';
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END CHAR;
ARCHITECTURE SYN OF char IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
BEGIN
q <= sub_wire0(7 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
address_aclr_a => "NONE",
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => "Unbenannt1.hex",
intended_device_family => "Cyclone III",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 128,
operation_mode => "ROM",
outdata_aclr_a => "NONE",
outdata_reg_a => "CLOCK0",
widthad_a => 7,
width_a => 8,
width_byteena_a => 1
)
PORT MAP (
address_a => address,
clock0 => clock,
q_a => sub_wire0
);
END SYN;
-- ============================================================
-- 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 "Unbenannt1.hex"
-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "128"
-- 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 "7"
-- 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 "Unbenannt1.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 "128"
-- 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 "7"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: USED_PORT: address 0 0 7 0 INPUT NODEFVAL "address[6..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 7 0 address 0 0 7 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 CHAR.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL CHAR.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL CHAR.cmp FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL CHAR.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL CHAR_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

131
2048_MiST/rtl/Game.vhd Normal file
View File

@@ -0,0 +1,131 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.GAME_TYPES.ALL;
entity GAME is
port
(
-- INPUT
clk_50Mhz : IN STD_LOGIC;
PS2_CLK : IN STD_LOGIC;
PS2_DAT : IN STD_LOGIC;
reset : IN STD_LOGIC;
-- OUTPUT
hsync,
vsync : OUT STD_LOGIC;
red,
green,
blue : OUT STD_LOGIC_VECTOR(3 downto 0)
);
end GAME;
architecture Behavioural of GAME is
-- Output Clock Generator
signal clock_25Mhz: STD_LOGIC;
-- Output Keyboard
signal keyCode: STD_LOGIC_VECTOR(7 downto 0);
-- Output Controller
signal boot : STD_LOGIC;
signal won : STD_LOGIC;
signal lost : STD_LOGIC;
signal movepadDirection : STD_LOGIC_VECTOR(3 downto 0);
-- Output Datapath
signal goingReady : STD_LOGIC;
signal isgameover : STD_LOGIC;
signal isvictory : STD_LOGIC;
signal box_values : GAME_GRID;
signal score : INTEGER RANGE 0 to 9999;
BEGIN
ClockDivider: entity work.GAME_CLKGENERATOR
port map
(
-- INPUT
clock => clk_50Mhz,
-- OUTPUT
clock_mezzi => clock_25Mhz
);
Keyboard: entity work.GAME_KEYBOARD
port map
(
-- INPUT
clk => clock_25Mhz,
keyboardClock => PS2_CLK,
keyboardData => PS2_DAT,
-- OUTPUT
keyCode => keyCode
);
ControlUnit: entity work.GAME_CONTROL
port map
(
-- INPUT
clk => clock_25Mhz,
-- from Keyboard
keyboardData => keyCode,
-- from Datapath
goingReady => goingReady,
isgameover => isgameover,
isvictory => isvictory,
-- OUTPUT
boot => boot,
won => won,
lost => lost,
movepadDirection => movepadDirection
);
Datapath: entity work.GAME_DATA
port map
(
-- INPUT
clk => clock_25Mhz,
-- from ControlUnit
bootstrap => boot or reset,
movepadDirection => movepadDirection,
-- OUTPUT
goingReady => goingReady,
isgameover => isgameover,
isvictory => isvictory,
box_values => box_values,
score => score
);
View: entity work.GAME_VIEW
port map
(
-- INPUT
clk => clock_25Mhz,
-- from Datapath
box_values => box_values,
score => score,
-- from ControlUnit
bootstrap => boot or reset,
lost => lost,
won => won,
-- OUTPUT
hsync => hsync,
vsync => vsync,
red => red,
green => green,
blue => blue
);
end Behavioural;

130
2048_MiST/rtl/Game.vhd.bak Normal file
View File

@@ -0,0 +1,130 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.GAME_TYPES.ALL;
entity GAME is
port
(
-- INPUT
clk_50Mhz : IN STD_LOGIC;
PS2_CLK : IN STD_LOGIC;
PS2_DAT : IN STD_LOGIC;
-- OUTPUT
hsync,
vsync : OUT STD_LOGIC;
red,
green,
blue : OUT STD_LOGIC_VECTOR(3 downto 0)
);
end GAME;
architecture Behavioural of GAME is
-- Output Clock Generator
signal clock_25Mhz: STD_LOGIC;
-- Output Keyboard
signal keyCode: STD_LOGIC_VECTOR(7 downto 0);
-- Output Controller
signal boot : STD_LOGIC;
signal won : STD_LOGIC;
signal lost : STD_LOGIC;
signal movepadDirection : STD_LOGIC_VECTOR(3 downto 0);
-- Output Datapath
signal goingReady : STD_LOGIC;
signal isgameover : STD_LOGIC;
signal isvictory : STD_LOGIC;
signal box_values : GAME_GRID;
signal score : INTEGER RANGE 0 to 9999;
BEGIN
ClockDivider: entity work.GAME_CLKGENERATOR
port map
(
-- INPUT
clock => clk_50Mhz,
-- OUTPUT
clock_mezzi => clock_25Mhz
);
Keyboard: entity work.GAME_KEYBOARD
port map
(
-- INPUT
clk => clock_25Mhz,
keyboardClock => PS2_CLK,
keyboardData => PS2_DAT,
-- OUTPUT
keyCode => keyCode
);
ControlUnit: entity work.GAME_CONTROL
port map
(
-- INPUT
clk => clock_25Mhz,
-- from Keyboard
keyboardData => keyCode,
-- from Datapath
goingReady => goingReady,
isgameover => isgameover,
isvictory => isvictory,
-- OUTPUT
boot => boot,
won => won,
lost => lost,
movepadDirection => movepadDirection
);
Datapath: entity work.GAME_DATA
port map
(
-- INPUT
clk => clock_25Mhz,
-- from ControlUnit
bootstrap => boot,
movepadDirection => movepadDirection,
-- OUTPUT
goingReady => goingReady,
isgameover => isgameover,
isvictory => isvictory,
box_values => box_values,
score => score
);
View: entity work.GAME_VIEW
port map
(
-- INPUT
clk => clock_25Mhz,
-- from Datapath
box_values => box_values,
score => score,
-- from ControlUnit
bootstrap => boot,
lost => lost,
won => won,
-- OUTPUT
hsync => hsync,
vsync => vsync,
red => red,
green => green,
blue => blue
);
end Behavioural;

199
2048_MiST/rtl/Game_BOX.vhd Normal file
View File

@@ -0,0 +1,199 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.GAME_TYPES.ALL;
entity GAME_BOX is
generic
(
XPOS : IN NATURAL;
YPOS : IN NATURAL
);
port
(
-- INPUT
clk : IN STD_LOGIC;
pixel_x : IN INTEGER RANGE 0 to 1000;
pixel_y : IN INTEGER RANGE 0 to 500;
number : IN INTEGER RANGE 0 to 2500;
-- OUTPUT
color : OUT STD_LOGIC_VECTOR(11 downto 0); -- colore attuale del box
drawBox : OUT STD_LOGIC := '0' -- disegna il box quando drawBox = 1
);
end GAME_BOX;
architecture box_arch of GAME_BOX is
-- Dimensioni fisse di tutti i box
constant larghezza : integer range 0 to 300 := 150;
constant altezza : integer range 0 to 200 := 105;
-- Coordinate finali del cubo sullo schermo
constant MAX_X : integer range 0 to 1000 := XPOS + larghezza; -- larghezza
constant MAX_Y : integer range 0 to 500 := YPOS + altezza; -- altezza
-- Coordinate delle cifre sullo schermo
constant X_CHAR : integer range 0 to 1000 := XPOS + larghezza/2;
constant Y_CHAR : integer range 0 to 500:= YPOS + altezza/2;
-- Segnali per la scrittura dei numeri a video
signal numberToDraw1: character;
signal numberToDraw2: character;
signal numberToDraw3: character;
signal numberToDraw4: character;
signal drawNum1 : std_logic;
signal drawNum2 : std_logic;
signal drawNum3 : std_logic;
signal drawNum4 : std_logic;
begin
CH1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR-20,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw1,
drawChar => drawNum1
);
CH2: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR-10,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw2,
drawChar => drawNum2
);
CH3: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw3,
drawChar => drawNum3
);
CH4: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR+10,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw4,
drawChar => drawNum4
);
valueChange : process(number, drawNum1, drawNum2, drawNum3, drawNum4, clk)
begin
if(clk'event and clk = '1')
then
if not(drawNum1 = '1' or drawNum2 = '1' or drawNum3 = '1' or drawNum4 = '1')
then
case number is
when 0 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= NUL;
numbertoDraw4 <= NUL;
color <= COLOR_0;
when 2 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= '2';
numbertoDraw4 <= NUL;
color <= COLOR_2;
when 4 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= '4';
numbertoDraw4 <= NUL;
color <= COLOR_4;
when 8 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= '8';
numbertoDraw4 <= NUL;
color <= COLOR_8;
when 16 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '1';
numberToDraw3 <= '6';
numbertoDraw4 <= NUL;
color <= COLOR_16;
when 32 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '3';
numberToDraw3 <= '2';
numbertoDraw4 <= NUL;
color <= COLOR_32;
when 64 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '6';
numberToDraw3 <= '4';
numbertoDraw4 <= NUL;
color <= COLOR_64;
when 128 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '1';
numberToDraw3 <= '2';
numbertoDraw4 <= '8';
color <= COLOR_128;
when 256 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '2';
numberToDraw3 <= '5';
numbertoDraw4 <= '6';
color <= COLOR_256;
when 512 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '5';
numberToDraw3 <= '1';
numbertoDraw4 <= '2';
color <= COLOR_512;
when 1024 =>
numberToDraw1 <= '1';
numberToDraw2 <= '0';
numberToDraw3 <= '2';
numbertoDraw4 <= '4';
color <= COLOR_1024;
when 2048 =>
numberToDraw1 <= '2';
numberToDraw2 <= '0';
numberToDraw3 <= '4';
numbertoDraw4 <= '8';
color <= COLOR_2048;
when others =>
numberToDraw4 <= NUL;
numberToDraw3 <= NUL;
numberToDraw2 <= NUL;
numbertoDraw1 <= NUL;
color <= COLOR_BLACK;
end case;
else
color <= COLOR_BLACK;
end if;
end if;
end process valueChange;
drawBox <= '1'
when
(pixel_x >= XPOS and pixel_x <= MAX_X and pixel_y >= YPOS and pixel_y <= MAX_Y)
else
'0';
end box_arch;

View File

@@ -0,0 +1,199 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.GAME_TYPES.ALL;
entity GAME_BOX is
generic
(
XPOS : IN NATURAL;
YPOS : IN NATURAL
);
port
(
-- INPUT
clk : IN STD_LOGIC;
pixel_x : IN INTEGER RANGE 0 to 1000;
pixel_y : IN INTEGER RANGE 0 to 500;
number : IN INTEGER RANGE 0 to 2500;
-- OUTPUT
color : OUT STD_LOGIC_VECTOR(11 downto 0); -- colore attuale del box
drawBox : OUT STD_LOGIC := '0' -- disegna il box quando drawBox = 1
);
end GAME_BOX;
architecture box_arch of GAME_BOX is
-- Dimensioni fisse di tutti i box
constant larghezza : integer range 0 to 300 := 150;
constant altezza : integer range 0 to 200 := 105;
-- Coordinate finali del cubo sullo schermo
constant MAX_X : integer range 0 to 1000 := XPOS + larghezza; -- larghezza
constant MAX_Y : integer range 0 to 500 := YPOS + altezza; -- altezza
-- Coordinate delle cifre sullo schermo
constant X_CHAR : integer range 0 to 1000 := XPOS + larghezza/2;
constant Y_CHAR : integer range 0 to 500:= YPOS + altezza/2;
-- Segnali per la scrittura dei numeri a video
signal numberToDraw1: character;
signal numberToDraw2: character;
signal numberToDraw3: character;
signal numberToDraw4: character;
signal drawNum1 : std_logic;
signal drawNum2 : std_logic;
signal drawNum3 : std_logic;
signal drawNum4 : std_logic;
begin
CH1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR-20,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw1,
drawChar => drawNum1
);
CH2: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR-10,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw2,
drawChar => drawNum2
);
CH3: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw3,
drawChar => drawNum3
);
CH4: entity work.GAME_CHDISPLAY
generic map
(
XPOS => X_CHAR+10,
YPOS => Y_CHAR
)
port map
(
pixel_x => pixel_x,
pixel_y => pixel_y,
char_code => numberToDraw4,
drawChar => drawNum4
);
valueChange : process(number, drawNum1, drawNum2, drawNum3, drawNum4, clk)
begin
if(clk'event and clk = '1')
then
if not(drawNum1 = '1' or drawNum2 = '1' or drawNum3 = '1' or drawNum4 = '1')
then
case number is
when 0 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= NUL;
numbertoDraw4 <= NUL;
color <= COLOR_0;
when 2 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= '2';
numbertoDraw4 <= NUL;
color <= COLOR_2;
when 4 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= '4';
numbertoDraw4 <= NUL;
color <= COLOR_4;
when 8 =>
numberToDraw1 <= NUL;
numberToDraw2 <= NUL;
numberToDraw3 <= '8';
numbertoDraw4 <= NUL;
color <= COLOR_8;
when 16 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '1';
numberToDraw3 <= '6';
numbertoDraw4 <= NUL;
color <= COLOR_16;
when 32 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '3';
numberToDraw3 <= '2';
numbertoDraw4 <= NUL;
color <= COLOR_32;
when 64 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '6';
numberToDraw3 <= '4';
numbertoDraw4 <= NUL;
color <= COLOR_64;
when 128 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '1';
numberToDraw3 <= '2';
numbertoDraw4 <= '8';
color <= COLOR_128;
when 256 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '2';
numberToDraw3 <= '5';
numbertoDraw4 <= '6';
color <= COLOR_256;
when 512 =>
numberToDraw1 <= NUL;
numberToDraw2 <= '5';
numberToDraw3 <= '1';
numbertoDraw4 <= '2';
color <= COLOR_512;
when 1024 =>
numberToDraw1 <= '1';
numberToDraw2 <= '0';
numberToDraw3 <= '2';
numbertoDraw4 <= '4';
color <= COLOR_1024;
when 2048 =>
numberToDraw1 <= '2';
numberToDraw2 <= '0';
numberToDraw3 <= '4';
numbertoDraw4 <= '8';
color <= COLOR_2048;
when others =>
numberToDraw4 <= NUL;
numberToDraw3 <= NUL;
numberToDraw2 <= NUL;
numbertoDraw1 <= NUL;
color <= COLOR_BLACK;
end case;
else
color <= COLOR_BLACK;
end if;
end if;
end process valueChange;
drawBox <= '1'
when
(pixel_x >= XPOS and pixel_x <= MAX_X and pixel_y >= YPOS and pixel_y <= MAX_Y)
else
'0';
end box_arch;

View File

@@ -0,0 +1,63 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
entity Game_CHDISPLAY is
-- Coordinate del box
generic
(
XPOS : IN NATURAL;
YPOS : IN NATURAL
);
port
(
-- INPUT
pixel_x : IN INTEGER RANGE 0 to 1000;
pixel_y : IN INTEGER RANGE 0 to 500;
char_code : IN CHARACTER;
-- OUTPUT
drawChar : OUT STD_LOGIC := '0' -- disegna il char quando drawChar = 1
);
end Game_CHDISPLAY;
architecture arch of Game_CHDISPLAY is
-- Dimensioni fisse di tutti i caratteri
constant larghezza : integer range 0 to 10 := 9;
constant altezza : integer range 0 to 20 := 16;
-- Coordinate finali del carattere sullo schermo
constant MAX_X : integer range 0 to 1000 := XPOS + larghezza; -- larghezza
constant MAX_Y : integer range 0 to 500 := YPOS + altezza; -- altezza
-- Segnali per il disegno dei caratteri su schermo
signal charAddr : STD_LOGIC_VECTOR(6 downto 0); -- Indirizzo del carattere sulla ROM
signal rowAddr : STD_LOGIC_VECTOR(3 downto 0); -- Numero della riga di pixel del singolo carattere (0-15)
signal charOut : STD_LOGIC_VECTOR(7 downto 0); -- Vettore di visualizzazione del carattere alla linea impostata
begin
CHROM: entity work.GAME_CHROM
port map
(
char_addr => charAddr,
row_addr => rowAddr,
data => charOut
);
codeChange : process(char_code, pixel_x, pixel_y)
begin
rowAddr <= std_logic_vector(to_unsigned(pixel_y-YPOS, rowAddr'length)); -- i-esima riga (0-15)
charAddr <= std_logic_vector(to_unsigned(character'pos(char_code), charAddr'length)); -- codice carattere (0-127)
end process codeChange;
drawChar <= '1'
when
pixel_x >= XPOS and -- limite alto del carattere
pixel_x < MAX_X and -- limite basso del carattere
pixel_y >= YPOS and -- limite sinistro del carattere
pixel_y < MAX_Y and -- limite destro del carattere
charOut(pixel_x-XPOS-1) = '1'
else
'0';
end arch;

View File

@@ -0,0 +1,63 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
entity Game_CHDISPLAY is
-- Coordinate del box
generic
(
XPOS : IN NATURAL;
YPOS : IN NATURAL
);
port
(
-- INPUT
pixel_x : IN INTEGER RANGE 0 to 1000;
pixel_y : IN INTEGER RANGE 0 to 500;
char_code : IN CHARACTER;
-- OUTPUT
drawChar : OUT STD_LOGIC := '0' -- disegna il char quando drawChar = 1
);
end Game_CHDISPLAY;
architecture arch of Game_CHDISPLAY is
-- Dimensioni fisse di tutti i caratteri
constant larghezza : integer range 0 to 10 := 9;
constant altezza : integer range 0 to 20 := 16;
-- Coordinate finali del carattere sullo schermo
constant MAX_X : integer range 0 to 1000 := XPOS + larghezza; -- larghezza
constant MAX_Y : integer range 0 to 500 := YPOS + altezza; -- altezza
-- Segnali per il disegno dei caratteri su schermo
signal charAddr : STD_LOGIC_VECTOR(6 downto 0); -- Indirizzo del carattere sulla ROM
signal rowAddr : STD_LOGIC_VECTOR(3 downto 0); -- Numero della riga di pixel del singolo carattere (0-15)
signal charOut : STD_LOGIC_VECTOR(7 downto 0); -- Vettore di visualizzazione del carattere alla linea impostata
begin
CHROM: entity work.GAME_CHROM
port map
(
char_addr => charAddr,
row_addr => rowAddr,
data => charOut
);
codeChange : process(char_code, pixel_x, pixel_y)
begin
rowAddr <= std_logic_vector(to_unsigned(pixel_y-YPOS, rowAddr'length)); -- i-esima riga (0-15)
charAddr <= std_logic_vector(to_unsigned(character'pos(char_code), charAddr'length)); -- codice carattere (0-127)
end process codeChange;
drawChar <= '1'
when
pixel_x >= XPOS and -- limite alto del carattere
pixel_x < MAX_X and -- limite basso del carattere
pixel_y >= YPOS and -- limite sinistro del carattere
pixel_y < MAX_Y and -- limite destro del carattere
charOut(pixel_x-XPOS-1) = '1'
else
'0';
end arch;

2220
2048_MiST/rtl/Game_CHROM.vhd Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY GAME_CLKGENERATOR IS
PORT
(
-- INPUT
clock : IN STD_LOGIC;
-- OUTPUT
clock_mezzi : OUT STD_LOGIC
);
END GAME_CLKGENERATOR;
ARCHITECTURE Behavioral OF GAME_CLKGENERATOR IS
SIGNAL counter : STD_LOGIC_VECTOR(0 DOWNTO 0);
BEGIN
PROCESS (clock)
BEGIN
IF clock = '0' AND clock'event THEN
counter <= counter + 1;
END IF;
END PROCESS;
clock_mezzi <= counter(0);
END Behavioral;

View File

@@ -0,0 +1,97 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.GAME_TYPES.ALL;
ENTITY GAME_CONTROL IS
PORT
(
-- INPUT
clk : IN STD_LOGIC;
keyboardData: IN STD_LOGIC_VECTOR (7 downto 0);
goingReady : IN STD_LOGIC;
isgameover : IN STD_LOGIC;
isvictory : IN STD_LOGIC;
-- OUTPUT
boot : OUT STD_LOGIC;
lost : OUT STD_LOGIC;
won : OUT STD_LOGIC;
-- usiamo 4 bit anche se ne basterebbero 2 per descrivere le 4 direzioni
movepadDirection : OUT STD_LOGIC_VECTOR(3 downto 0)
);
end GAME_CONTROL;
ARCHITECTURE behavior of GAME_CONTROL IS
BEGIN
PROCESS
variable state : GAME_STATE := bootstrap;
constant keyRESET : std_logic_vector(7 downto 0):=X"76";
constant keyRIGHT : std_logic_vector(7 downto 0):=X"74";
constant keyLEFT : std_logic_vector(7 downto 0):=X"6B";
constant keyUP : std_logic_vector(7 downto 0):=X"75";
constant keyDOWN : std_logic_vector(7 downto 0):=X"72";
constant dirUP : std_logic_vector(3 downto 0):="1000";
constant dirDOWN : std_logic_vector(3 downto 0):="0001";
constant dirLEFT : std_logic_vector(3 downto 0):="0100";
constant dirRIGHT : std_logic_vector(3 downto 0):="0010";
BEGIN
WAIT UNTIL(clk'EVENT) AND (clk = '1');
case state IS
when BOOTSTRAP =>
boot <= '1';
lost <= '0';
won <= '0';
IF(goingReady = '1')
THEN
state := PLAYING;
boot <= '0';
END IF;
when PLAYING =>
if(isgameover = '1')
then
state := GAMEOVER;
end if;
if(isvictory = '1')
then
state := VICTORY;
end if;
case keyboardData is
when keyRIGHT => -- do move right
movepadDirection <= dirRIGHT;
when keyLEFT => -- do move left
movepadDirection <= dirLEFT;
when KEYUP => -- do move right
movepadDirection <= dirUP;
when KEYDOWN => -- do move left
movepadDirection <= dirDOWN;
when others => -- do nothing
movepadDirection <= "0000";
end case;
when GAMEOVER =>
lost <= '1';
when VICTORY =>
won <= '1';
when others =>
NULL;
END case;
IF(keyboardData=keyRESET)
THEN
boot <= '1';
state := BOOTSTRAP;
END IF;
END PROCESS;
END behavior;

1159
2048_MiST/rtl/Game_DATA.vhd Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,417 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.GAME_TYPES.ALL;
entity GAME_GRID_VIEW is
port
(
-- INPUT
clk : IN STD_LOGIC;
pixel_x : IN INTEGER RANGE 0 to 1000;
pixel_y : IN INTEGER RANGE 0 to 500;
box_values : IN GAME_GRID;
-- OUTPUT
color : OUT STD_LOGIC_VECTOR(11 downto 0); -- colore da mandare in VGA
drawGrid : OUT STD_LOGIC := '0' -- disegna la Grid quando = 1
);
end GAME_GRID_VIEW;
ARCHITECTURE grid_arch of GAME_GRID_VIEW IS
-- Posizioni fisse di tutti i box
constant XfirstColumn : integer range 0 to 1000 := 16;
constant YfirstRow : integer range 0 to 500 := 32;
constant XsecondColumn : integer range 0 to 1000 := 168;
constant YsecondRow : integer range 0 to 500 := 139;
constant XthirdColumn : integer range 0 to 1000 := 320;
constant YthirdRow : integer range 0 to 500 := 246;
constant XfourthColumn : integer range 0 to 1000 := 472;
constant YfourthRow : integer range 0 to 500 := 353;
-- Segnali per il disegno dei box e il relativo colore
signal drawbox1 : STD_LOGIC;
signal color1 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox2 : STD_LOGIC;
signal color2 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox3 : STD_LOGIC;
signal color3 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox4 : STD_LOGIC;
signal color4 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox5 : STD_LOGIC;
signal color5 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox6 : STD_LOGIC;
signal color6 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox7 : STD_LOGIC;
signal color7 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox8 : STD_LOGIC;
signal color8 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox9 : STD_LOGIC;
signal color9 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox10: STD_LOGIC;
signal color10 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox11: STD_LOGIC;
signal color11 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox12: STD_LOGIC;
signal color12 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox13: STD_LOGIC;
signal color13 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox14: STD_LOGIC;
signal color14 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox15: STD_LOGIC;
signal color15 : STD_LOGIC_VECTOR(11 downto 0);
signal drawbox16: STD_LOGIC;
signal color16 : STD_LOGIC_VECTOR(11 downto 0);
BEGIN
BOX1: entity work.GAME_BOX
generic map
(
XPOS => XfirstColumn,
YPOS => YfirstRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(0,0),
drawbox => drawbox1,
color => color1
);
BOX2: entity work.GAME_BOX
generic map
(
XPOS => XsecondColumn,
YPOS => YfirstRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(0,1),
drawbox => drawbox2,
color => color2
);
BOX3: entity work.GAME_BOX
generic map
(
XPOS => XthirdColumn,
YPOS => YfirstRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(0,2),
drawbox => drawbox3,
color => color3
);
BOX4: entity work.GAME_BOX
generic map
(
XPOS => XfourthColumn,
YPOS => YfirstRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(0,3),
drawbox => drawbox4,
color => color4
);
BOX5: entity work.GAME_BOX
generic map
(
XPOS => XfirstColumn,
YPOS => YsecondRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(1,0),
drawbox => drawbox5,
color => color5
);
BOX6: entity work.GAME_BOX
generic map
(
XPOS => XsecondColumn,
YPOS => YsecondRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(1,1),
drawbox => drawbox6,
color => color6
);
BOX7: entity work.GAME_BOX
generic map
(
XPOS => XthirdColumn,
YPOS => YsecondRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(1,2),
drawbox => drawbox7,
color => color7
);
BOX8: entity work.GAME_BOX
generic map
(
XPOS => XfourthColumn,
YPOS => YsecondRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(1,3),
drawbox => drawbox8,
color => color8
);
BOX9: entity work.GAME_BOX
generic map
(
XPOS => XfirstColumn,
YPOS => YthirdRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(2,0),
drawbox => drawbox9,
color => color9
);
BOX10: entity work.GAME_BOX
generic map
(
XPOS => XsecondColumn,
YPOS => YthirdRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(2,1),
drawbox => drawbox10,
color => color10
);
BOX11: entity work.GAME_BOX
generic map
(
XPOS => XthirdColumn,
YPOS => YthirdRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(2,2),
drawbox => drawbox11,
color => color11
);
BOX12: entity work.GAME_BOX
generic map
(
XPOS => XfourthColumn,
YPOS => YthirdRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(2,3),
drawbox => drawbox12,
color => color12
);
BOX13: entity work.GAME_BOX
generic map
(
XPOS => XfirstColumn,
YPOS => YfourthRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(3,0),
drawbox => drawbox13,
color => color13
);
BOX14: entity work.GAME_BOX
generic map
(
XPOS => XsecondColumn,
YPOS => YfourthRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(3,1),
drawbox => drawbox14,
color => color14
);
BOX15: entity work.GAME_BOX
generic map
(
XPOS => XthirdColumn,
YPOS => YfourthRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(3,2),
drawbox => drawbox15,
color => color15
);
BOX16: entity work.GAME_BOX
generic map
(
XPOS => XfourthColumn,
YPOS => YfourthRow
)
port map
(
clk => clk,
pixel_x => pixel_x,
pixel_y => pixel_y,
number => box_values(3,3),
drawbox => drawbox16,
color => color16
);
drawBoxes : process
(
drawbox1, drawbox2, drawbox3, drawbox4, drawbox5, drawbox6, drawbox7, drawbox8,
drawbox9, drawbox10, drawbox11, drawbox12, drawbox13, drawbox14, drawbox15, drawbox16,
color1, color2, color3, color4, color5, color6, color7, color8,
color9, color10, color11, color12, color13, color14, color15, color16
)
begin
-- non ha bisogno di essere sincrono in quanto la lettura viene fatta dalla view ad ogni
-- fronte positivo del clock (da ricordare!)
--- DISEGNO DI OGNI BOX
color <= (others => '0');
IF(drawbox1 = '1')
THEN
color <= color1;
END IF;
IF(drawbox2 = '1')
THEN
color <= color2;
END IF;
IF(drawbox3 = '1')
THEN
color <= color3;
END IF;
IF(drawbox4 = '1')
THEN
color <= color4;
END IF;
IF(drawbox5 = '1')
THEN
color <= color5;
END IF;
IF(drawbox6 = '1')
THEN
color <= color6;
END IF;
IF(drawbox7 = '1')
THEN
color <= color7;
END IF;
IF(drawbox8 = '1')
THEN
color <= color8;
END IF;
IF(drawbox9 = '1')
THEN
color <= color9;
END IF;
IF(drawbox10 = '1')
THEN
color <= color10;
END IF;
IF(drawbox11 = '1')
THEN
color <= color11;
END IF;
IF(drawbox12 = '1')
THEN
color <= color12;
END IF;
IF(drawbox13 = '1')
THEN
color <= color13;
END IF;
IF(drawbox14 = '1')
THEN
color <= color14;
END IF;
IF(drawbox15 = '1')
THEN
color <= color15;
END IF;
IF(drawbox16 = '1')
THEN
color <= color16;
END IF;
end process drawBoxes;
drawGrid <= '1'
when
(
drawbox1 = '1' or drawbox2 = '1' or drawbox3='1' or drawbox4 = '1' or
drawbox5 = '1' or drawbox6 = '1' or drawbox7='1' or drawbox8 = '1' or
drawbox9 = '1' or drawbox10 = '1' or drawbox11='1' or drawbox12 = '1' or
drawbox13 = '1' or drawbox14 = '1' or drawbox15='1' or drawbox16 = '1'
)
else
'0';
END grid_arch;

View File

@@ -0,0 +1,78 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity GAME_KEYBOARD is
Port
(
-- INPUT
clk : in STD_LOGIC;
keyboardClock : in STD_LOGIC;
keyboardData : in STD_LOGIC;
-- OUTPUT
keyCode : out STD_LOGIC_VECTOR(7 downto 0)
);
end GAME_KEYBOARD;
architecture Behavioral of GAME_KEYBOARD is
signal bitCount : INTEGER range 0 to 100 := 0;
signal scanCodeReady : STD_LOGIC := '0';
signal scanCode : STD_LOGIC_VECTOR(7 downto 0);
signal breakReceived : STD_LOGIC_VECTOR(1 downto 0) := "00";
-- Breakcode viene generato quando viene rilasciato il dito dal tasto della tastiera
constant breakCode : STD_LOGIC_VECTOR(7 downto 0) := X"F0";
begin
Keyboard : process(keyboardClock)
begin
if falling_edge(keyboardClock)
then
if (bitCount = 0 and keyboardData = '0')
then
scanCodeReady <= '0';
bitCount <= bitCount + 1;
elsif bitCount > 0 and bitCount < 9
then
-- si shifta di un bit lo scancode da sinistra
scancode <= keyboardData & scancode(7 downto 1);
bitCount <= bitCount + 1;
-- bit di parità
elsif (bitCount = 9)
then
bitCount <= bitCount + 1;
-- fine messaggio
elsif (bitCount = 10)
then
scanCodeReady <= '1';
bitCount <= 0;
end if;
end if;
end process Keyboard;
sendData : process(scanCodeReady, scanCode)
begin
if (scanCodeReady'event and scanCodeReady = '1')
then
case breakReceived is
when "00" =>
if (scanCode = breakCode)
then
breakReceived <= "01";
end if;
keyCode <= scanCode;
when "01" =>
breakReceived <= "10";
keyCode <= breakCode;
when "10" =>
breakReceived <= "00";
keyCode <= breakCode;
when others =>
keyCode <= scanCode;
end case;
end if;
end process sendData;
end Behavioral;

View File

@@ -0,0 +1,32 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.GAME_TYPES.ALL;
ENTITY GAME_RANDOMGEN IS
PORT
(
-- INPUT
clk : IN STD_LOGIC;
-- OUTPUT
random_num : OUT STD_LOGIC_VECTOR(3 downto 0)
);
END GAME_RANDOMGEN;
ARCHITECTURE behavior of GAME_RANDOMGEN IS
BEGIN
PROCESS(clk)
variable rand_temp : std_logic_vector(GRID_WIDTH-1 downto 0):=("1000");
variable temp : std_logic := '0';
BEGIN
if(rising_edge(clk)) then
temp := rand_temp(GRID_WIDTH-1) xor rand_temp(GRID_WIDTH-2);
rand_temp(GRID_WIDTH-1 downto 1) := rand_temp(GRID_WIDTH-2 downto 0);
rand_temp(0) := temp;
end if;
random_num <= rand_temp;
END PROCESS;
END behavior;

View File

@@ -0,0 +1,65 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
PACKAGE GAME_TYPES IS
constant GRID_WIDTH : INTEGER RANGE 0 to 8 := 4;
constant GRID_HEIGHT : INTEGER RANGE 0 to 8 := 4;
-- game state type
type GAME_STATE is (bootstrap, playing, gameover, victory);
-- data type
type DATA_STATE is (init, randupdate, checkupdate, idle, merge1, move1, merge2, move2, merge3, move3);
type GAME_GRID is array (GRID_HEIGHT-1 downto 0, GRID_WIDTH -1 downto 0) of integer;
-- tipi per la grafica
subtype RGB_COLOR is std_logic_vector(11 downto 0);
-- Colori standard
constant COLOR_BLACK : RGB_COLOR := X"000";
constant COLOR_BLUE : RGB_COLOR := X"00F";
constant COLOR_BROWN : RGB_COLOR := X"841";
constant COLOR_CYAN : RGB_COLOR := X"0FF";
constant COLOR_CREAM : RGB_COLOR := X"EFE";
constant COLOR_GREEN : RGB_COLOR := X"080";
constant COLOR_GREEN_D : RGB_COLOR := X"0F8";
constant COLOR_GREY : RGB_COLOR := X"888";
constant COLOR_GREY_D : RGB_COLOR := X"BBB";
constant COLOR_IVORY : RGB_COLOR := X"FFE";
constant COLOR_LIME : RGB_COLOR := X"0F0";
constant COLOR_MAGENTA : RGB_COLOR := X"F0F";
constant COLOR_MAROON : RGB_COLOR := X"800";
constant COLOR_NAVY : RGB_COLOR := X"008";
constant COLOR_OLIVE : RGB_COLOR := X"880";
constant COLOR_ORANGE : RGB_COLOR := X"FA0";
constant COLOR_ORANGE_D : RGB_COLOR := X"F80";
constant COLOR_PINK : RGB_COLOR := X"FCC";
constant COLOR_PURPLE : RGB_COLOR := X"808";
constant COLOR_RED : RGB_COLOR := X"F00";
constant COLOR_SALMON : RGB_COLOR := X"F87";
constant COLOR_SILVER : RGB_COLOR := X"CCC";
constant COLOR_SLATEGRAY: RGB_COLOR := X"789";
constant COLOR_SNOW : RGB_COLOR := X"FEE";
constant COLOR_TEAL : RGB_COLOR := X"088";
constant COLOR_WHITE : RGB_COLOR := X"FFF";
constant COLOR_YELLOW : RGB_COLOR := X"FF0";
-- Colori personalizzati per il gioco
constant COLOR_BG : RGB_COLOR := COLOR_SLATEGRAY;
constant COLOR_BORDER : RGB_COLOR := COLOR_GREY_D;
constant COLOR_VICTORY : RGB_COLOR := X"C12";
constant COLOR_0 : RGB_COLOR := X"999";
constant COLOR_2 : RGB_COLOR := X"EED";
constant COLOR_4 : RGB_COLOR := X"FEC";
constant COLOR_8 : RGB_COLOR := X"EA7";
constant COLOR_16 : RGB_COLOR := X"E85";
constant COLOR_32 : RGB_COLOR := X"E65";
constant COLOR_64 : RGB_COLOR := X"E53";
constant COLOR_128 : RGB_COLOR := X"FE5";
constant COLOR_256 : RGB_COLOR := X"ED4";
constant COLOR_512 : RGB_COLOR := X"ED0";
constant COLOR_1024 : RGB_COLOR := X"EC0";
constant COLOR_2048 : RGB_COLOR := X"EB0";
END GAME_TYPES;

View File

@@ -0,0 +1,232 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.GAME_TYPES.ALL;
-- Definizioni delle funzioni e delle procedure contenute nel package
PACKAGE GAME_UTILS IS
FUNCTION digit_to_7seg (A: INTEGER RANGE 0 TO 9)
RETURN STD_LOGIC_VECTOR;
FUNCTION reverse (A: STD_LOGIC_VECTOR)
RETURN STD_LOGIC_VECTOR;
FUNCTION checkGameOver (values: GAME_GRID)
RETURN STD_LOGIC;
FUNCTION checkVictory (values: GAME_GRID)
RETURN STD_LOGIC;
PROCEDURE splitNumber
(
number : IN INTEGER RANGE 0 TO 9999;
X4, X3, X2, X1 : OUT INTEGER RANGE 0 TO 9
);
PROCEDURE convertCoord
(
position : IN INTEGER RANGE 0 TO 16;
X, Y : OUT INTEGER RANGE 0 TO 3
);
FUNCTION compare(curr_values: GAME_GRID; next_values: GAME_GRID)
RETURN STD_LOGIC;
END GAME_UTILS;
PACKAGE BODY GAME_UTILS IS
-- Conversione da cifra a vettore di bit per 7 segmenti
FUNCTION digit_to_7seg (A: INTEGER RANGE 0 TO 9) RETURN STD_LOGIC_VECTOR IS
-- Risultato: uscita 7 bit per 7 segmenti
VARIABLE RESULT: STD_LOGIC_VECTOR(6 downto 0);
BEGIN
CASE A IS
-- Logica negativa
WHEN 0 => RESULT := NOT"0111111";
WHEN 1 => RESULT := NOT"0000110";
WHEN 2 => RESULT := NOT"1011011";
WHEN 3 => RESULT := NOT"1001111";
WHEN 4 => RESULT := NOT"1100110";
WHEN 5 => RESULT := NOT"1101101";
WHEN 6 => RESULT := NOT"1111101";
WHEN 7 => RESULT := NOT"0000111";
WHEN 8 => RESULT := NOT"1111111";
WHEN 9 => RESULT := NOT"1101111";
WHEN -- caso impossibile
OTHERS => RESULT := NOT"0000000";
END CASE;
RETURN RESULT;
END digit_to_7seg;
-- Inversione di un generico vettore
FUNCTION reverse (A: STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
-- Risultato: vettore della stessa dimensione del vettore d'ingresso
VARIABLE RESULT : STD_LOGIC_VECTOR(A'RANGE);
ALIAS AA : STD_LOGIC_VECTOR(A'REVERSE_RANGE) IS A;
BEGIN
FOR i IN AA'RANGE LOOP
RESULT(i) := AA(i);
END LOOP;
RETURN RESULT;
END reverse;
-- Funz. che stabilisce se la partita sia stata persa o meno
FUNCTION checkGameOver(values: GAME_GRID) RETURN std_logic IS
variable full : STD_LOGIC := '1';
variable mergeable : STD_LOGIC := '0';
variable result : STD_LOGIC := '0';
BEGIN
for i in 0 to 3 loop
for j in 0 to 3 loop
if(values(i,j) = 0)
then
full := '0';
end if;
end loop;
end loop;
for i in 0 to 2 loop
for j in 0 to 2 loop
if(
(values(i,j) = values(i+1,j)) or
(values(i,j) = values(i,j+1))
)
then
mergeable := '1';
end if;
end loop;
end loop;
-- controllo ultima riga
for i in 1 to 3 loop
if(
(values(3,i-1) = values(3,i)) or
(values(i-1,3) = values(i,3))
)
then
mergeable := '1';
end if;
end loop;
result := full and (not mergeable);
return result;
END FUNCTION checkGameOver;
--Funz. che stabilisce se la partita sia terminata con la vittoria
FUNCTION checkVictory(values: GAME_GRID) RETURN std_logic IS
variable result : STD_LOGIC := '0';
constant victory_score : INTEGER RANGE 0 to 3000 := 2048;
BEGIN
-- Controlla in tutte le celle se sia stato raggiunto il valore necessario per la vittoria
for i in 0 to 3 loop
for j in 0 to 3 loop
if(values(i,j) = victory_score)
then
result := '1';
end if;
end loop;
end loop;
return result;
END FUNCTION checkVictory;
-- Procedura per suddividere un intero 0-9999 nelle sue 4 cifre
PROCEDURE splitNumber (SIGNAL number: IN INTEGER RANGE 0 TO 9999; SIGNAL X4, X3, X2, X1: OUT INTEGER RANGE 0 TO 9) IS
variable digit4, digit3, digit2, digit1 : INTEGER RANGE 0 TO 9;
variable temp : INTEGER RANGE 0 TO 9999;
BEGIN
temp := number;
IF(temp > 999)
THEN
digit4 := temp/1000;
temp := temp-digit4*1000;
ELSE
digit4 := 0;
END IF;
IF(temp > 99)
THEN
digit3 := temp/100;
temp := temp-digit3*100;
ELSE
digit3 := 0;
END IF;
IF(temp > 9)
THEN
digit2 := temp/10;
temp := temp-digit2*10;
ELSE
digit2 := 0;
END IF;
digit1 := temp;
X4 <= digit4;
X3 <= digit3;
X2 <= digit2;
X1 <= digit1;
END splitNumber;
-- Procedura per convertire un numero 1-16 nella relativa coordinata (x,y)
PROCEDURE convertCoord (SIGNAL position: IN INTEGER RANGE 0 TO 16; VARIABLE X, Y: OUT INTEGER RANGE 0 TO 3) IS
BEGIN
case position is
when 1 =>
x := 0;
y := 0;
when 2 =>
x := 0;
y := 1;
when 3 =>
x := 0;
y := 2;
when 4 =>
x := 0;
y := 3;
when 5 =>
x := 1;
y := 0;
when 6 =>
x := 1;
y := 1;
when 7 =>
x := 1;
y := 2;
when 8 =>
x := 1;
y := 3;
when 9 =>
x := 2;
y := 0;
when 10 =>
x := 2;
y := 1;
when 11 =>
x := 2;
y := 2;
when 12 =>
x := 2;
y := 3;
when 13 =>
x := 3;
y := 0;
when 14 =>
x := 3;
y := 1;
when 15 =>
x := 3;
y := 2;
when 16 =>
x := 3;
y := 3;
when others =>
NULL;
end case;
END convertCoord;
FUNCTION compare(curr_values: GAME_GRID; next_values: GAME_GRID) RETURN std_logic IS
variable result : STD_LOGIC := '1';
BEGIN
for i in 0 to 3 loop
for j in 0 to 3 loop
if not (curr_values(i,j) = next_values(i,j))
then
result := '0';
end if;
end loop;
end loop;
return result;
END compare;
END GAME_UTILS;

594
2048_MiST/rtl/Game_VIEW.vhd Normal file
View File

@@ -0,0 +1,594 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.GAME_TYPES.ALL;
ENTITY GAME_VIEW IS
PORT
(
-- INPUTs
clk : IN STD_LOGIC;
-- MODEL STATUS
box_values : IN GAME_GRID;
score : IN INTEGER RANGE 0 to 9999;
bootstrap,
won,
lost : IN STD_LOGIC;
-- OUTPUTs
hsync,
vsync : OUT STD_LOGIC;
red,
green,
blue : OUT STD_LOGIC_VECTOR(3 downto 0)
);
end GAME_VIEW;
ARCHITECTURE behavior of GAME_VIEW IS
-- Sync Counters
shared variable h_cnt : integer range 0 to 1000;
shared variable v_cnt : integer range 0 to 500;
-- Segnali per il disegno della griglia e del colore dei box
signal drawGrid : STD_LOGIC;
signal colorGrid : STD_LOGIC_VECTOR(11 downto 0);
-- Segnali per il disegno dei caratteri su schermo : autori
signal drawCharC : STD_LOGIC;
signal drawCharO : STD_LOGIC;
signal drawCharL : STD_LOGIC;
signal drawCharA : STD_LOGIC;
signal drawCharC1 : STD_LOGIC;
signal drawCharE : STD_LOGIC;
signal drawCharSep : STD_LOGIC;
signal drawCharG : STD_LOGIC;
signal drawCharE1 : STD_LOGIC;
signal drawCharZ : STD_LOGIC;
signal drawCharZ1 : STD_LOGIC;
signal drawCharI : STD_LOGIC;
-- game over
signal drawGoG : STD_LOGIC;
signal drawGoA : STD_LOGIC;
signal drawGoM : STD_LOGIC;
signal drawGoE : STD_LOGIC;
signal drawGoO : STD_LOGIC;
signal drawGoV : STD_LOGIC;
signal drawGoE1: STD_LOGIC;
signal drawGoR : STD_LOGIC;
-- you win
signal drawYwY : STD_LOGIC;
signal drawYwO : STD_LOGIC;
signal drawYwU : STD_LOGIC;
signal drawYwW : STD_LOGIC;
signal drawYwI : STD_LOGIC;
signal drawYwN : STD_LOGIC;
BEGIN
--Disegno caratteri : autori
CHC: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 16,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'C',
drawChar => drawCharC
);
CHO: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 26,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'o',
drawChar => drawCharO
);
CHL: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 36,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'l',
drawChar => drawCharL
);
CHA: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 46,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'a',
drawChar => drawCharA
);
CHC1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 56,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'c',
drawChar => drawCharC1
);
CHE: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 66,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'e',
drawChar => drawCharE
);
CHSEP: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 76,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => '-',
drawChar => drawCharSep
);
CHG: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 86,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'G',
drawChar => drawCharG
);
CHE1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 96,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'e',
drawChar => drawCharE1
);
CHZ: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 106,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'z',
drawChar => drawCharZ
);
CHZ1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 116,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'z',
drawChar => drawCharZ1
);
CHI: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 126,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'i',
drawChar => drawCharI
);
-- disegno caratteri : game over
CHGOG: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 280,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'G',
drawChar => drawGoG
);
CHGOA: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 290,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'A',
drawChar => drawGoA
);
CHGOM: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 300,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'M',
drawChar => drawGoM
);
CHGOE: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 310,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'E',
drawChar => drawGoE
);
--over
CHGOO: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 330,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'O',
drawChar => drawGoO
);
CHGOV: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 340,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'V',
drawChar => drawGoV
);
CHGOE1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 350,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'E',
drawChar => drawGoE1
);
CHGOR: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 360,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'R',
drawChar => drawGoR
);
CHYWY: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 280,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'Y',
drawChar => drawYwY
);
CHYWO: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 290,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'O',
drawChar => drawYwO
);
CHYWU: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 300,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'U',
drawChar => drawYwU
);
CHYWW: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 320,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'W',
drawChar => drawYwW
);
CHYWI: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 330,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'I',
drawChar => drawYwI
);
CHYWN: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 340,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'N',
drawChar => drawYwN
);
GRID: entity work.GAME_GRID_VIEW
port map
(
clk => clk,
pixel_x => h_cnt,
pixel_y => v_cnt,
box_values => box_values,
drawGrid => drawGrid,
color => colorGrid
);
PROCESS
-- HSYNC e VSYNC
variable h_sync : STD_LOGIC;
variable v_sync : STD_LOGIC;
-- Enable del video
variable horizontal_en : STD_LOGIC;
variable vertical_en : STD_LOGIC;
variable video_en : STD_LOGIC;
-- Segnale colore RGB a 12 bit
variable colorRGB : STD_LOGIC_VECTOR(11 downto 0);
-- Bordi Schermo
constant leftBorder : INTEGER RANGE 0 to 1000 := 15;
constant rightBorder : INTEGER RANGE 0 to 1000 := 625;
constant upBorder : INTEGER RANGE 0 to 500 := 30;
constant downBorder : INTEGER RANGE 0 to 500 := 460;
BEGIN
WAIT UNTIL(clk'EVENT) AND (clk = '1');
-- Reset Horizontal Counter
-- (al valore 799, anzich<63> 640, per rispettare i tempi di Front Porch)
IF (h_cnt = 799)
THEN
h_cnt := 0;
ELSE
h_cnt := h_cnt + 1;
END IF;
-- Disegno Bordi
IF
(
h_cnt <= leftBorder OR -- BORDO LEFT
h_cnt >= rightBorder OR -- BORDO RIGHT
v_cnt <= upBorder OR -- BORDO UP
v_cnt >= downBorder -- BORDO DOWN
)
THEN
colorRGB := COLOR_BORDER;
-- SE NON <20> BORDO, <20> SFONDO
ELSE
colorRGB := COLOR_BG;
END IF;
-- Disegno griglia di gioco
IF (drawGrid = '1')
THEN
colorRGB := colorGrid;
END IF;
-- Disegno "Colace-Gezzi"
IF
(
drawCharC='1' OR drawCharO='1' OR drawCharL='1' OR
drawCharA='1' OR drawCharC1='1' OR drawCharE='1' OR
drawCharSep='1' OR drawCharG='1' OR drawCharE1='1' OR
drawCharZ='1' OR drawCharZ1='1' OR drawCharI='1'
)
THEN
colorRGB := COLOR_TEAL;
END IF;
-- Disegno "GAME OVER"
IF
(
(drawGoG='1' OR drawGoA='1' OR drawGoM='1' OR drawGoE='1' OR
drawGoO='1' OR drawGoV='1' OR drawGoE1='1' OR drawGoR='1') AND
lost = '1'
)
THEN
colorRGB := COLOR_TEAL;
END IF;
-- Disegno "YOU WIN"
IF
(
(drawYwY='1' OR drawYwO='1' OR drawYwU='1' OR
drawYwW='1' OR drawYwI='1' OR drawYwN='1' ) AND
won = '1'
)
THEN
colorRGB := COLOR_VICTORY;
END IF;
-- H_SYNC
IF (h_cnt <= 755 AND h_cnt >= 659)
THEN
h_sync := '0';
ELSE
h_sync := '1';
END IF;
-- V_SYNC
IF (v_cnt >= 524 AND h_cnt >= 699)
THEN
v_cnt := 0;
ELSIF (h_cnt = 699)
THEN
v_cnt := v_cnt + 1;
END IF;
IF (v_cnt = 490 OR v_cnt = 491)
THEN
v_sync := '0';
ELSE
v_sync := '1';
END IF;
-- Horizontal Data Enable
-- (dati di riga validi, ossia nel range orizzontale 0-639)
IF (h_cnt <= 639)
THEN
horizontal_en := '1';
ELSE
horizontal_en := '0';
END IF;
-- Vertical Data Enable
-- (dati di riga validi, ossia nel range verticale 0-479)
IF (v_cnt <= 479)
THEN
vertical_en := '1';
ELSE
vertical_en := '0';
END IF;
-- Video Enable <20> AND tra i due data enable
video_en := horizontal_en AND vertical_en;
-- Assegnamento segnali fisici a VGA
red(3) <= colorRGB(11) AND video_en;
red(2) <= colorRGB(10) AND video_en;
red(1) <= colorRGB(9) AND video_en;
red(0) <= colorRGB(8) AND video_en;
green(3) <= colorRGB(7) AND video_en;
green(2) <= colorRGB(6) AND video_en;
green(1) <= colorRGB(5) AND video_en;
green(0) <= colorRGB(4) AND video_en;
blue(3) <= colorRGB(3) AND video_en;
blue(2) <= colorRGB(2) AND video_en;
blue(1) <= colorRGB(1) AND video_en;
blue(0) <= colorRGB(0) AND video_en;
hsync <= h_sync;
vsync <= v_sync;
END PROCESS;
END behavior;

View File

@@ -0,0 +1,594 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.GAME_TYPES.ALL;
ENTITY GAME_VIEW IS
PORT
(
-- INPUTs
clk : IN STD_LOGIC;
-- MODEL STATUS
box_values : IN GAME_GRID;
score : IN INTEGER RANGE 0 to 9999;
bootstrap,
won,
lost : IN STD_LOGIC;
-- OUTPUTs
hsync,
vsync : OUT STD_LOGIC;
red,
green,
blue : OUT STD_LOGIC_VECTOR(3 downto 0)
);
end GAME_VIEW;
ARCHITECTURE behavior of GAME_VIEW IS
-- Sync Counters
shared variable h_cnt : integer range 0 to 1000;
shared variable v_cnt : integer range 0 to 500;
-- Segnali per il disegno della griglia e del colore dei box
signal drawGrid : STD_LOGIC;
signal colorGrid : STD_LOGIC_VECTOR(11 downto 0);
-- Segnali per il disegno dei caratteri su schermo : autori
signal drawCharC : STD_LOGIC;
signal drawCharO : STD_LOGIC;
signal drawCharL : STD_LOGIC;
signal drawCharA : STD_LOGIC;
signal drawCharC1 : STD_LOGIC;
signal drawCharE : STD_LOGIC;
signal drawCharSep : STD_LOGIC;
signal drawCharG : STD_LOGIC;
signal drawCharE1 : STD_LOGIC;
signal drawCharZ : STD_LOGIC;
signal drawCharZ1 : STD_LOGIC;
signal drawCharI : STD_LOGIC;
-- game over
signal drawGoG : STD_LOGIC;
signal drawGoA : STD_LOGIC;
signal drawGoM : STD_LOGIC;
signal drawGoE : STD_LOGIC;
signal drawGoO : STD_LOGIC;
signal drawGoV : STD_LOGIC;
signal drawGoE1: STD_LOGIC;
signal drawGoR : STD_LOGIC;
-- you win
signal drawYwY : STD_LOGIC;
signal drawYwO : STD_LOGIC;
signal drawYwU : STD_LOGIC;
signal drawYwW : STD_LOGIC;
signal drawYwI : STD_LOGIC;
signal drawYwN : STD_LOGIC;
BEGIN
--Disegno caratteri : autori
CHC: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 16,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'C',
drawChar => drawCharC
);
CHO: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 26,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'o',
drawChar => drawCharO
);
CHL: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 36,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'l',
drawChar => drawCharL
);
CHA: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 46,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'a',
drawChar => drawCharA
);
CHC1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 56,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'c',
drawChar => drawCharC1
);
CHE: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 66,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'e',
drawChar => drawCharE
);
CHSEP: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 76,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => '-',
drawChar => drawCharSep
);
CHG: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 86,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'G',
drawChar => drawCharG
);
CHE1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 96,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'e',
drawChar => drawCharE1
);
CHZ: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 106,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'z',
drawChar => drawCharZ
);
CHZ1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 116,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'z',
drawChar => drawCharZ1
);
CHI: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 126,
YPOS => 12
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'i',
drawChar => drawCharI
);
-- disegno caratteri : game over
CHGOG: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 280,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'G',
drawChar => drawGoG
);
CHGOA: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 290,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'A',
drawChar => drawGoA
);
CHGOM: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 300,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'M',
drawChar => drawGoM
);
CHGOE: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 310,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'E',
drawChar => drawGoE
);
--over
CHGOO: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 330,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'O',
drawChar => drawGoO
);
CHGOV: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 340,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'V',
drawChar => drawGoV
);
CHGOE1: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 350,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'E',
drawChar => drawGoE1
);
CHGOR: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 360,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'R',
drawChar => drawGoR
);
CHYWY: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 280,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'Y',
drawChar => drawYwY
);
CHYWO: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 290,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'O',
drawChar => drawYwO
);
CHYWU: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 300,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'U',
drawChar => drawYwU
);
CHYWW: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 320,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'W',
drawChar => drawYwW
);
CHYWI: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 330,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'I',
drawChar => drawYwI
);
CHYWN: entity work.GAME_CHDISPLAY
generic map
(
XPOS => 340,
YPOS => 232
)
port map
(
pixel_x => h_cnt,
pixel_y => v_cnt,
char_code => 'N',
drawChar => drawYwN
);
GRID: entity work.GAME_GRID_VIEW
port map
(
clk => clk,
pixel_x => h_cnt,
pixel_y => v_cnt,
box_values => box_values,
drawGrid => drawGrid,
color => colorGrid
);
PROCESS
-- HSYNC e VSYNC
variable h_sync : STD_LOGIC;
variable v_sync : STD_LOGIC;
-- Enable del video
variable horizontal_en : STD_LOGIC;
variable vertical_en : STD_LOGIC;
variable video_en : STD_LOGIC;
-- Segnale colore RGB a 12 bit
variable colorRGB : STD_LOGIC_VECTOR(11 downto 0);
-- Bordi Schermo
constant leftBorder : INTEGER RANGE 0 to 1000 := 15;
constant rightBorder : INTEGER RANGE 0 to 1000 := 625;
constant upBorder : INTEGER RANGE 0 to 500 := 30;
constant downBorder : INTEGER RANGE 0 to 500 := 460;
BEGIN
WAIT UNTIL(clk'EVENT) AND (clk = '1');
-- Reset Horizontal Counter
-- (al valore 799, anzich<63> 640, per rispettare i tempi di Front Porch)
IF (h_cnt = 799)
THEN
h_cnt := 0;
ELSE
h_cnt := h_cnt + 1;
END IF;
-- Disegno Bordi
IF
(
h_cnt <= leftBorder OR -- BORDO LEFT
h_cnt >= rightBorder OR -- BORDO RIGHT
v_cnt <= upBorder OR -- BORDO UP
v_cnt >= downBorder -- BORDO DOWN
)
THEN
colorRGB := COLOR_BORDER;
-- SE NON <20> BORDO, <20> SFONDO
ELSE
colorRGB := COLOR_BG;
END IF;
-- Disegno griglia di gioco
IF (drawGrid = '1')
THEN
colorRGB := colorGrid;
END IF;
-- Disegno "Colace-Gezzi"
IF
(
drawCharC='1' OR drawCharO='1' OR drawCharL='1' OR
drawCharA='1' OR drawCharC1='1' OR drawCharE='1' OR
drawCharSep='1' OR drawCharG='1' OR drawCharE1='1' OR
drawCharZ='1' OR drawCharZ1='1' OR drawCharI='1'
)
THEN
colorRGB := COLOR_TEAL;
END IF;
-- Disegno "GAME OVER"
IF
(
(drawGoG='1' OR drawGoA='1' OR drawGoM='1' OR drawGoE='1' OR
drawGoO='1' OR drawGoV='1' OR drawGoE1='1' OR drawGoR='1') AND
lost = '1'
)
THEN
colorRGB := COLOR_TEAL;
END IF;
-- Disegno "YOU WIN"
IF
(
(drawYwY='1' OR drawYwO='1' OR drawYwU='1' OR
drawYwW='1' OR drawYwI='1' OR drawYwN='1' ) AND
won = '1'
)
THEN
colorRGB := COLOR_VICTORY;
END IF;
-- H_SYNC
IF (h_cnt <= 755 AND h_cnt >= 659)
THEN
h_sync := '0';
ELSE
h_sync := '1';
END IF;
-- V_SYNC
IF (v_cnt >= 524 AND h_cnt >= 699)
THEN
v_cnt := 0;
ELSIF (h_cnt = 699)
THEN
v_cnt := v_cnt + 1;
END IF;
IF (v_cnt = 490 OR v_cnt = 491)
THEN
v_sync := '0';
ELSE
v_sync := '1';
END IF;
-- Horizontal Data Enable
-- (dati di riga validi, ossia nel range orizzontale 0-639)
IF (h_cnt <= 639)
THEN
horizontal_en := '1';
ELSE
horizontal_en := '0';
END IF;
-- Vertical Data Enable
-- (dati di riga validi, ossia nel range verticale 0-479)
IF (v_cnt <= 479)
THEN
vertical_en := '1';
ELSE
vertical_en := '0';
END IF;
-- Video Enable <20> AND tra i due data enable
video_en := horizontal_en AND vertical_en;
-- Assegnamento segnali fisici a VGA
red(3) <= colorRGB(11) AND video_en;
red(2) <= colorRGB(10) AND video_en;
red(1) <= colorRGB(9) AND video_en;
red(0) <= colorRGB(8) AND video_en;
green(3) <= colorRGB(7) AND video_en;
green(2) <= colorRGB(6) AND video_en;
green(1) <= colorRGB(5) AND video_en;
green(0) <= colorRGB(4) AND video_en;
blue(3) <= colorRGB(3) AND video_en;
blue(2) <= colorRGB(2) AND video_en;
blue(1) <= colorRGB(1) AND video_en;
blue(0) <= colorRGB(0) AND video_en;
hsync <= h_sync;
vsync <= v_sync;
END PROCESS;
END behavior;

View File

@@ -0,0 +1,129 @@
:1000000000000000000000000000000000000000F0
:1000100000007E81A58181BD9981817E0000000064
:1000200000007EFFDBFFFFC3E7FFFF7E0000000054
:10003000000000006CFEFEFEFE7C38100000000098
:100040000000000010387CFE7C381000000000002A
:10005000000000183C3CE7E7E718183C00000000EF
:10006000000000183C7EFFFF7E18183C00000000D6
:10007000000000000000183C3C18000000000000D8
:10008000FFFFFFFFFFFFE7C3C3E7FFFFFFFFFFFF28
:1000900000000000003C664242663C000000000098
:1000A000FFFFFFFFFFC399BDBD99C3FFFFFFFFFF28
:1000B00000001E0E1A3278CCCCCCCC7800000000A8
:1000C00000003C666666663C187E1818000000005A
:1000D00000003F333F3030303070F0E0000000006F
:1000E00000007F637F6363636367E7E6C00000002F
:1000F0000000001818DB3CE73CDB1818000000008B
:100100000080C0E0F0F8FEF8F0E0C08000000000E1
:100110000002060E1E3EFE3E1E0E060200000000FD
:100120000000183C7E1818187E3C180000000000E3
:100130000000666666666666660066660000000029
:1001400000007FDBDBDB7B1B1B1B1B1B000000009D
:10015000007CC660386CC6C66C380CC67C000000DB
:100160000000000000000000FEFEFEFE0000000097
:100170000000183C7E1818187E3C187E30000000E5
:100180000000183C7E1818181818181800000000F5
:100190000000181818181818187E3C1800000000E5
:1001A0000000000000180CFE0C1800000000000009
:1001B00000000000003060FE603000000000000021
:1001C000000000000000C0C0C0FE000000000000F1
:1001D00000000000002466FF66240000000000000C
:1001E000000000001038387C7CFEFE00000000009B
:1001F00000000000FEFE7C7C38381000000000008B
:1002000000000000000000000000000000000000EE
:100210000000183C3C3C181818001818000000009A
:100220000066666624000000000000000000000078
:100230000000006C6CFE6C6C6CFE6C6C00000000CE
:1002400018187CC6C2C07C060686C67C181800003A
:1002500000000000C2C60C183060C6860000000016
:100260000000386C6C3876DCCCCCCC76000000001A
:10027000003030306000000000000000000000008E
:1002800000000C18303030303030180C0000000006
:10029000000030180C0C0C0C0C0C18300000000086
:1002A0000000000000663CFF3C660000000000000B
:1002B000000000000018187E181800000000000060
:1002C00000000000000000000018181830000000B6
:1002D000000000000000007E0000000000000000A0
:1002E00000000000000000000000181800000000DE
:1002F0000000000002060C183060C0800000000002
:1003000000007CC6C6CEDEF6E6C6C67C0000000055
:1003100000001838781818181818187E0000000007
:1003200000007CC6060C183060C0C6FE000000004D
:1003300000007CC606063C060606C67C00000000DF
:1003400000000C1C3C6CCCFE0C0C0C1E00000000D1
:100350000000FEC0C0C0FC060606C67C000000000F
:1003600000003860C0C0FCC6C6C6C67C00000000E5
:100370000000FEC606060C183030303000000000C9
:1003800000007CC6C6C67CC6C6C6C67C000000008F
:1003900000007CC6C6C67E0606060C78000000007B
:1003A00000000000181800000018180000000000ED
:1003B00000000000181800000018183000000000AD
:1003C000000000060C18306030180C060000000019
:1003D00000000000007E00007E0000000000000021
:1003E0000000006030180C060C183060000000009F
:1003F00000007CC6C60C1818180018180000000071
:1004000000007CC6C6C6DEDEDEDCC07C000000006C
:10041000000010386CC6C6FEC6C6C6C60000000086
:100420000000FC6666667C66666666FC000000008E
:1004300000003C66C2C0C0C0C0C2663C00000000F4
:100440000000F86C6666666666666CF80000000080
:100450000000FE6662687868606266FE0000000068
:100460000000FE6662687868606060F0000000006E
:1004700000003C66C2C0C0DEC6C6663A000000008E
:100480000000C6C6C6C6FEC6C6C6C6C60000000078
:1004900000003C18181818181818183C0000000024
:1004A00000001E0C0C0C0C0CCCCCCC780000000016
:1004B0000000E666666C78786C6666E60000000010
:1004C0000000F06060606060606266FE0000000036
:1004D0000000C3E7FFFFDBC3C3C3C3C300000000CA
:1004E0000000C6E6F6FEDECEC6C6C6C600000000A8
:1004F00000007CC6C6C6C6C6C6C6C67C00000000D4
:100500000000FC6666667C60606060F000000000D1
:1005100000007CC6C6C6C6C6C6D6DE7C0C0E000071
:100520000000FC6666667C6C666666E6000000009D
:1005300000007CC6C660380C06C6C67C0000000001
:100540000000FFDB991818181818183C000000006C
:100550000000C6C6C6C6C6C6C6C6C67C0000000029
:100560000000C3C3C3C3C3C3C3663C18000000007C
:100570000000C3C3C3C3C3DBDBFF6666000000002B
:100580000000C3C3663C18183C66C3C300000000EB
:100590000000C3C3C3663C181818183C00000000D4
:1005A0000000FFC3860C183060C1C3FF00000000CC
:1005B00000003C30303030303030303C0000000043
:1005C00000000080C0E070381C0E06020000000031
:1005D00000003C0C0C0C0C0C0C0C0C3C0000000043
:1005E00010386CC600000000000000000000000091
:1005F00000000000000000000000000000FF0000FC
:100600003030180000000000000000000000000072
:100610000000000000780C7CCCCCCC760000000000
:100620000000E06060786C666666667C0000000032
:1006300000000000007CC6C0C0C0C67C00000000F6
:1006400000001C0C0C3C6CCCCCCCCC760000000028
:1006500000000000007CC6FEC0C0C67C0000000098
:100660000000386C6460F060606060F000000000C2
:10067000000000000076CCCCCCCCCC7C0CCC78003C
:100680000000E060606C7666666666E6000000006A
:1006900000001818003818181818183C000000003E
:1006A00000000606000E06060606060666663C0004
:1006B0000000E06060666C78786C66E60000000020
:1006C00000003818181818181818183C00000000F6
:1006D0000000000000E6FFDBDBDBDBDB00000000EE
:1006E0000000000000DC66666666666600000000CA
:1006F00000000000007CC6C6C6C6C67C0000000024
:100700000000000000DC66666666667C6060F000E3
:10071000000000000076CCCCCCCCCC7C0C0C1E00B5
:100720000000000000DC7666606060F00000000001
:1007300000000000007CC660380CC67C0000000091
:100740000000103030FC30303030361C000000002B
:100750000000000000CCCCCCCCCCCC76000000005B
:100760000000000000C3C3C3C3663C1800000000C3
:100770000000000000C3C3C3DBDBFF660000000015
:100780000000000000C3663C183C66C30000000087
:100790000000000000C6C6C6C6C6C67E060CF8002D
:1007A0000000000000FECC183060C6FE0000000013
:1007B00000000E18181870181818180E0000000005
:1007C0000000181818180018181818180000000051
:1007D0000000701818180E18181818700000000083
:1007E000000076DC000000000000000000000000B7
:1007F0000000000010386CC6C6C6FE0000000000F5
:00000001FF

View File

@@ -0,0 +1,2 @@
`define BUILD_DATE "180204"
`define BUILD_TIME "164559"

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.sv"
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,95 @@
module game2048_mist (
input CLOCK_27,
output LED,
output SPI_DO,
input SPI_DI,
input SPI_SCK,
input SPI_SS3,
input CONF_DATA0,
output VGA_HS,
output VGA_VS,
output [5:0]VGA_R,
output [5:0]VGA_G,
output [5:0]VGA_B
);
assign LED = 1;
`include "rtl/build_id.sv"
localparam CONF_STR = {
"2048;;",
"T2,Reset;",
"V,v1.00.",`BUILD_DATE
};
wire clk50, clk12p5;
wire ps2_kbd_clk, ps2_kbd_data;
wire [3:0] r, g, b;
wire hs, vs;
wire ypbpr;
wire [31:0] status;
wire [1:0] buttons, switches;
pll pll (
.inclk0(CLOCK_27),
.c0(clk50),
.c1(clk12p5)
);
GAME GAME (
.clk_50Mhz (clk50 ),
.reset (status[0] || buttons[1] || status[2]),
.PS2_CLK (ps2_kbd_clk ),
.PS2_DAT (ps2_kbd_data ),
.hsync (hs ),
.vsync (vs ),
.red (r ),
.green (g ),
.blue (b )
);
mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io
(
.clk_sys (clk50 ),
.conf_str (CONF_STR ),
.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(1 ),
.ypbpr (ypbpr ),
.ps2_kbd_clk (ps2_kbd_clk ),
.ps2_kbd_data (ps2_kbd_data ),
.status (status )
);
video_mixer #(.LINE_LENGTH(640), .HALF_DEPTH(1)) video_mixer
(
.clk_sys (clk50 ),
.ce_pix (clk12p5 ),
.ce_pix_actual (clk12p5 ),
.SPI_SCK (SPI_SCK ),
.SPI_SS3 (SPI_SS3 ),
.SPI_DI (SPI_DI ),
.R (r ),
.G (g ),
.B (b ),
.HSync (hs ),
.VSync (vs ),
.VGA_R (VGA_R ),
.VGA_G (VGA_G ),
.VGA_B (VGA_B ),
.VGA_VS (VGA_VS ),
.VGA_HS (VGA_HS ),
.ypbpr_full (1 ),
.ypbpr (ypbpr ),
.line_start (0 ),
.mono (0 )
);
endmodule

View File

@@ -0,0 +1,103 @@
module game2048_mist (
input CLOCK_27,
output LED,
// SPI interface to arm io controller
output SPI_DO,
input SPI_DI,
input SPI_SCK,
input SPI_SS2,
input SPI_SS3,
input SPI_SS4,
input CONF_DATA0,
// video
output VGA_HS,
output VGA_VS,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B
);
assign LED = 1;
`include "rtl/build_id.sv"
localparam CONF_STR = {
"GAMEBOY;;",
"O45,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
"V,v1.00.",`BUILD_DATE
};
wire clk50, clk12p5;
wire ps2_kbd_clk, ps2_kbd_data;
wire [3:0] r, g, b;
wire hs, vs;
wire ypbpr;
wire [31:0] status;
wire [1:0] buttons, switches;
pll pll (
.inclk0(CLOCK_27),
.c0(clk50),
.c1(clk12p5)
);
gb gb (
.clk_50Mhz (clk50 ),
.PS2_CLK (ps2_kbd_clk ),
.PS2_DAT (ps2_kbd_data ),
.hsync (hs ),
.vsync (vs ),
.red (r ),
.green (g ),
.blue (b ),
);
mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io
(
.clk_sys (clk50 ),
.conf_str (CONF_STR ),
.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(1 ),
.ypbpr (ypbpr ),
.ps2_kbd_clk (ps2_kbd_clk ),
.ps2_kbd_data (ps2_kbd_data ),
.status (status )
);
video_mixer #(.LINE_LENGTH(640), .HALF_DEPTH(1)) video_mixer
(
.clk_sys (clk50 ),
.ce_pix (clk12p5 ),
.ce_pix_actual (clk12p5 ),
.SPI_SCK (SPI_SCK ),
.SPI_SS3 (SPI_SS3 ),
.SPI_DI (SPI_DI ),
.R (r ),
.G (g ),
.B (b ),
.HSync (hs ),
.VSync (vs ),
.VGA_R (VGA_R ),
.VGA_G (VGA_G ),
.VGA_B (VGA_B ),
.VGA_VS (VGA_VS ),
.VGA_HS (VGA_HS ),
.scandoubler_disable(1 ),
.scanlines (scandoubler_disable ? 2'b00 : {status[5:4] == 3, status[5:4] == 2}),
.hq2x (status[5:4]==1),
.ypbpr_full (1 ),
.ypbpr (ypbpr ),
.line_start (0 ),
.mono (0 )
);
endmodule

454
2048_MiST/rtl/hq2x.sv Normal file
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

491
2048_MiST/rtl/mist_io.sv Normal file
View File

@@ -0,0 +1,491 @@
//
// 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,
input ps2_caps_led,
// ARM -> FPGA download
output reg ioctl_download = 0, // signal indicating an active download
output reg [7:0] ioctl_index, // menu index used to upload the file
output ioctl_wr,
output reg [23: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 [9: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;
wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1};
// 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];
// reading keyboard LED status
8'h1f:
spi_do <= kbd_led[~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 [23: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 [23: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
addr <= 0;
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
assign ioctl_wr = |ioctl_wrd;
reg [1:0] ioctl_wrd;
always@(negedge clk_sys) begin
reg rclkD, rclkD2;
rclkD <= rclk;
rclkD2 <= rclkD;
ioctl_wrd<= {ioctl_wrd[0],1'b0};
if(rclkD & ~rclkD2) begin
ioctl_dout <= data_w;
ioctl_addr <= addr_w;
ioctl_wrd <= 2'b11;
end
end
endmodule

179
2048_MiST/rtl/osd.sv Normal file
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

4
2048_MiST/rtl/pll.qip Normal file
View File

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

337
2048_MiST/rtl/pll.v Normal file
View File

@@ -0,0 +1,337 @@
// 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.0 Build 162 10/23/2013 SJ Web Edition
// ************************************************************
//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.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll (
inclk0,
c0,
c1,
locked);
input inclk0;
output c0;
output c1;
output locked;
wire [4:0] sub_wire0;
wire sub_wire2;
wire [0:0] sub_wire6 = 1'h0;
wire [0:0] sub_wire3 = sub_wire0[0:0];
wire [1:1] sub_wire1 = sub_wire0[1:1];
wire c1 = sub_wire1;
wire locked = sub_wire2;
wire c0 = sub_wire3;
wire sub_wire4 = inclk0;
wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};
altpll altpll_component (
.inclk (sub_wire5),
.clk (sub_wire0),
.locked (sub_wire2),
.activeclock (),
.areset (1'b0),
.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 = 50,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 54,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 25,
altpll_component.clk1_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 37037,
altpll_component.intended_device_family = "Cyclone III",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_UNUSED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "OFF",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "27"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "54"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "50.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.500000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "50"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "25"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "50.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.50000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "27"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "54"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "25"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

135
2048_MiST/rtl/rom.v Normal file
View File

@@ -0,0 +1,135 @@
module rom();
localparam ROM = {
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7E,8'h81,8'hA5,8'h81,8'h81,8'hBD,8'h99,8'h81,8'h81,8'h7E,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7E,8'hFF,8'hDB,8'hFF,8'hFF,8'hC3,8'hE7,8'hFF,8'hFF,8'h7E,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h6C,8'hFE,8'hFE,8'hFE,8'hFE,8'h7C,8'h38,8'h10,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h10,8'h38,8'h7C,8'hFE,8'h7C,8'h38,8'h10,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h18,8'h3C,8'h3C,8'hE7,8'hE7,8'hE7,8'h18,8'h18,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h18,8'h3C,8'h7E,8'hFF,8'hFF,8'h7E,8'h18,8'h18,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h18,8'h3C,8'h3C,8'h18,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hE7,8'hC3,8'hC3,8'hE7,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h3C,8'h66,8'h42,8'h42,8'h66,8'h3C,8'h00,8'h00,8'h00,8'h00,8'h00,
8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hC3,8'h99,8'hBD,8'hBD,8'h99,8'hC3,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,
8'h00,8'h00,8'h1E,8'h0E,8'h1A,8'h32,8'h78,"11001100","11001100","11001100","11001100",8'h78,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h3C,8'h66,8'h66,8'h66,8'h66,8'h3C,8'h18,8'h7E,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"00111111","00110011","00111111","00110000","00110000","00110000","00110000","01110000","11110000","11100000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"01111111","01100011","01111111","01100011","01100011","01100011","01100011","01100111",8'hE7,"11100110","11000000",8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h18,8'h18,8'hDB,8'h3C,8'hE7,8'h3C,8'hDB,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,"10000000","11000000","11100000","11110000","11111000",8'hFE,"11111000","11110000","11100000","11000000","10000000",8'h00,8'h00,8'h00,8'h00,
8'h00,"00000010","00000110",8'h0E,8'h1E,"00111110",8'hFE,"00111110",8'h1E,8'h0E,"00000110","00000010",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h3C,8'h7E,8'h18,8'h18,8'h18,8'h7E,8'h3C,8'h18,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h66,8'h66,8'h66,8'h66,8'h66,8'h66,8'h66,8'h00,8'h66,8'h66,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"01111111",8'hDB,8'hDB,8'hDB,"01111011","00011011","00011011","00011011","00011011","00011011",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h7C,8'hC6,"01100000",8'h38,8'h6C,8'hC6,8'hC6,8'h6C,8'h38,"00001100",8'hC6,8'h7C,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'hFE,8'hFE,8'hFE,8'hFE,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h3C,8'h7E,8'h18,8'h18,8'h18,8'h7E,8'h3C,8'h18,8'h7E,"00110000",8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h3C,8'h7E,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h7E,8'h3C,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h18,"00001100",8'hFE,"00001100",8'h18,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"00110000","01100000",8'hFE,"01100000","00110000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,"11000000","11000000","11000000",8'hFE,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"00100100",8'h66,8'hFF,8'h66,"00100100",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h10,8'h38,8'h38,8'h7C,8'h7C,8'hFE,8'hFE,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'hFE,8'hFE,8'h7C,8'h7C,8'h38,8'h38,8'h10,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h3C,8'h3C,8'h3C,8'h18,8'h18,8'h18,8'h00,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h66,8'h66,8'h66,"00100100",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h6C,8'h6C,8'hFE,8'h6C,8'h6C,8'h6C,8'hFE,8'h6C,8'h6C,8'h00,8'h00,8'h00,8'h00,
8'h18,8'h18,8'h7C,8'hC6,"11000010","11000000",8'h7C,"00000110","00000110","10000110",8'hC6,8'h7C,8'h18,8'h18,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,"11000010",8'hC6,"00001100",8'h18,"00110000","01100000",8'hC6,"10000110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h38,8'h6C,8'h6C,8'h38,"01110110","11011100","11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
8'h00,"00110000","00110000","00110000","01100000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"00001100",8'h18,"00110000","00110000","00110000","00110000","00110000","00110000",8'h18,"00001100",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"00110000",8'h18,"00001100","00001100","00001100","00001100","00001100","00001100",8'h18,"00110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h66,8'h3C,8'hFF,8'h3C,8'h66,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h18,8'h18,8'h7E,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h18,8'h18,8'h18,"00110000",8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h7E,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,"00000010","00000110","00001100",8'h18,"00110000","01100000","11000000","10000000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,"11001110","11011110","11110110","11100110",8'hC6,8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h38,8'h78,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h7E,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,"00000110","00001100",8'h18,"00110000","01100000","11000000",8'hC6,8'hFE,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,"00000110","00000110",8'h3C,"00000110","00000110","00000110",8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"00001100","00011100",8'h3C,8'h6C,"11001100",8'hFE,"00001100","00001100","00001100",8'h1E,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hFE,"11000000","11000000","11000000","11111100","00000110","00000110","00000110",8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h38,"01100000","11000000","11000000","11111100",8'hC6,8'hC6,8'hC6,8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hFE,8'hC6,"00000110","00000110","00001100",8'h18,"00110000","00110000","00110000","00110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,8'hC6,8'h7C,8'hC6,8'hC6,8'hC6,8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,8'hC6,8'h7E,"00000110","00000110","00000110","00001100",8'h78,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h18,8'h18,8'h00,8'h00,8'h00,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h18,8'h18,8'h00,8'h00,8'h00,8'h18,8'h18,"00110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,"00000110","00001100",8'h18,"00110000","01100000","00110000",8'h18,"00001100","00000110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h7E,8'h00,8'h00,8'h7E,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,"01100000","00110000",8'h18,"00001100","00000110","00001100",8'h18,"00110000","01100000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,"00001100",8'h18,8'h18,8'h18,8'h00,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,8'hC6,"11011110","11011110","11011110","11011100","11000000",8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h10,8'h38,8'h6C,8'hC6,8'hC6,8'hFE,8'hC6,8'hC6,8'hC6,8'hC6,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"11111100",8'h66,8'h66,8'h66,8'h7C,8'h66,8'h66,8'h66,8'h66,"11111100",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h3C,8'h66,"11000010","11000000","11000000","11000000","11000000","11000010",8'h66,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"11111000",8'h6C,8'h66,8'h66,8'h66,8'h66,8'h66,8'h66,8'h6C,"11111000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hFE,8'h66,"01100010","01101000",8'h78,"01101000","01100000","01100010",8'h66,8'hFE,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hFE,8'h66,"01100010","01101000",8'h78,"01101000","01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h3C,8'h66,"11000010","11000000","11000000","11011110",8'hC6,8'hC6,8'h66,"00111010",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC6,8'hC6,8'hC6,8'hC6,8'hFE,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h3C,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h1E,"00001100","00001100","00001100","00001100","00001100","11001100","11001100","11001100",8'h78,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"11100110",8'h66,8'h66,8'h6C,8'h78,8'h78,8'h6C,8'h66,8'h66,"11100110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"11110000","01100000","01100000","01100000","01100000","01100000","01100000","01100010",8'h66,8'hFE,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC3,8'hE7,8'hFF,8'hFF,8'hDB,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC6,"11100110","11110110",8'hFE,"11011110","11001110",8'hC6,8'hC6,8'hC6,8'hC6,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"11111100",8'h66,8'h66,8'h66,8'h7C,"01100000","01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,"11010110","11011110",8'h7C,"00001100",8'h0E,8'h00,8'h00,
8'h00,8'h00,"11111100",8'h66,8'h66,8'h66,8'h7C,8'h6C,8'h66,8'h66,8'h66,"11100110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h7C,8'hC6,8'hC6,"01100000",8'h38,"00001100","00000110",8'hC6,8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hFF,8'hDB,8'h99,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'h66,8'h3C,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'hDB,8'hDB,8'hFF,8'h66,8'h66,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC3,8'hC3,8'h66,8'h3C,8'h18,8'h18,8'h3C,8'h66,8'hC3,8'hC3,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hC3,8'hC3,8'hC3,8'h66,8'h3C,8'h18,8'h18,8'h18,8'h18,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'hFF,8'hC3,"10000110","00001100",8'h18,"00110000","01100000","11000001",8'hC3,8'hFF,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h3C,"00110000","00110000","00110000","00110000","00110000","00110000","00110000","00110000",8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,"10000000","11000000","11100000","01110000",8'h38,"00011100",8'h0E,"00000110","00000010",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h3C,"00001100","00001100","00001100","00001100","00001100","00001100","00001100","00001100",8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h10,8'h38,8'h6C,8'hC6,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'hFF,8'h00,8'h00,
"00110000","00110000",8'h18,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h78,"00001100",8'h7C,"11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"11100000","01100000","01100000",8'h78,8'h6C,8'h66,8'h66,8'h66,8'h66,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,8'hC6,"11000000","11000000","11000000",8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"00011100","00001100","00001100",8'h3C,8'h6C,"11001100","11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,8'hC6,8'hFE,"11000000","11000000",8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h38,8'h6C,"01100100","01100000","11110000","01100000","01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"01110110","11001100","11001100","11001100","11001100","11001100",8'h7C,"00001100","11001100",8'h78,8'h00,
8'h00,8'h00,"11100000","01100000","01100000",8'h6C,"01110110",8'h66,8'h66,8'h66,8'h66,"11100110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h18,8'h00,8'h38,8'h18,8'h18,8'h18,8'h18,8'h18,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"00000110","00000110",8'h00,8'h0E,"00000110","00000110","00000110","00000110","00000110","00000110",8'h66,8'h66,8'h3C,8'h00,
8'h00,8'h00,"11100000","01100000","01100000",8'h66,8'h6C,8'h78,8'h78,8'h6C,8'h66,"11100110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h38,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h18,8'h3C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"11100110",8'hFF,8'hDB,8'hDB,8'hDB,8'hDB,8'hDB,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"11011100",8'h66,8'h66,8'h66,8'h66,8'h66,8'h66,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"11011100",8'h66,8'h66,8'h66,8'h66,8'h66,8'h7C,"01100000","01100000","11110000",8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"01110110","11001100","11001100","11001100","11001100","11001100",8'h7C,"00001100","00001100",8'h1E,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"11011100","01110110",8'h66,"01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,8'hC6,"01100000",8'h38,"00001100",8'hC6,8'h7C,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h10,"00110000","00110000","11111100","00110000","00110000","00110000","00110000","00110110","00011100",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,"11001100","11001100","11001100","11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hC3,8'h66,8'h3C,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hDB,8'hDB,8'hFF,8'h66,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'hC3,8'h66,8'h3C,8'h18,8'h3C,8'h66,8'hC3,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'hC6,8'h7E,"00000110","00001100","11111000",8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'hFE,"11001100",8'h18,"00110000","01100000",8'hC6,8'hFE,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h0E,8'h18,8'h18,8'h18,"01110000",8'h18,8'h18,8'h18,8'h18,8'h0E,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h18,8'h18,8'h18,8'h18,8'h00,8'h18,8'h18,8'h18,8'h18,8'h18,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"01110000",8'h18,8'h18,8'h18,8'h0E,8'h18,8'h18,8'h18,8'h18,"01110000",8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,"01110110","11011100",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h10,8'h38,8'h6C,8'hC6,8'hC6,8'hC6,8'hFE,8'h00,8'h00,8'h00,8'h00,8'h00
};
endmodule

131
2048_MiST/rtl/rom.v.bak Normal file
View File

@@ -0,0 +1,131 @@
constantROM:rom_type:=
(
-- 08'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 18'h00,8'h00,8'h7E,8'h81,8'hA5,8'h81,8'h81,8'hBD,8'h99,8'h81,8'h81,8'h7E,8'h00,8'h00,8'h00,8'h00,
-- 28'h00,8'h00,8'h7E,8'hFF,8'hDB,8'hFF,8'hFF,8'hC3,"11100111",8'hFF,8'hFF,8'h7E,8'h00,8'h00,8'h00,8'h00,
-- 38'h00,8'h00,8'h00,8'h00,"01101100",8'hFE,8'hFE,8'hFE,8'hFE,8'h7C,"00111000","00010000",8'h00,8'h00,8'h00,8'h00,
-- 48'h00,8'h00,8'h00,8'h00,"00010000","00111000",8'h7C,8'hFE,8'h7C,"00111000","00010000",8'h00,8'h00,8'h00,8'h00,8'h00,
-- 58'h00,8'h00,8'h00,"00011000",8'h3C,8'h3C,"11100111","11100111","11100111","00011000","00011000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 68'h00,8'h00,8'h00,"00011000",8'h3C,8'h7E,8'hFF,8'hFF,8'h7E,"00011000","00011000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 78'h00,8'h00,8'h00,8'h00,8'h00,8'h00,"00011000",8'h3C,8'h3C,"00011000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 88'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,"11100111",8'hC3,8'hC3,"11100111",8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,
-- 98'h00,8'h00,8'h00,8'h00,8'h00,8'h3C,"01100110","01000010","01000010","01100110",8'h3C,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 108'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hC3,8'h99,8'hBD,8'hBD,8'h99,8'hC3,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,
-- 118'h00,8'h00,"00011110",8'h0E,"00011010","00110010","01111000","11001100","11001100","11001100","11001100","01111000",8'h00,8'h00,8'h00,8'h00,
-- 128'h00,8'h00,8'h3C,"01100110","01100110","01100110","01100110",8'h3C,"00011000",8'h7E,"00011000","00011000",8'h00,8'h00,8'h00,8'h00,
-- 138'h00,8'h00,"00111111","00110011","00111111","00110000","00110000","00110000","00110000","01110000","11110000","11100000",8'h00,8'h00,8'h00,8'h00,
-- 148'h00,8'h00,"01111111","01100011","01111111","01100011","01100011","01100011","01100011","01100111","11100111","11100110","11000000",8'h00,8'h00,8'h00,
-- 158'h00,8'h00,8'h00,"00011000","00011000",8'hDB,8'h3C,"11100111",8'h3C,8'hDB,"00011000","00011000",8'h00,8'h00,8'h00,8'h00,
-- 168'h00,"10000000","11000000","11100000","11110000","11111000",8'hFE,"11111000","11110000","11100000","11000000","10000000",8'h00,8'h00,8'h00,8'h00,
-- 178'h00,"00000010","00000110",8'h0E,"00011110","00111110",8'hFE,"00111110","00011110",8'h0E,"00000110","00000010",8'h00,8'h00,8'h00,8'h00,
-- 188'h00,8'h00,"00011000",8'h3C,8'h7E,"00011000","00011000","00011000",8'h7E,8'h3C,"00011000",8'h00,8'h00,8'h00,8'h00,8'h00,
-- 198'h00,8'h00,"01100110","01100110","01100110","01100110","01100110","01100110","01100110",8'h00,"01100110","01100110",8'h00,8'h00,8'h00,8'h00,
-- 208'h00,8'h00,"01111111",8'hDB,8'hDB,8'hDB,"01111011","00011011","00011011","00011011","00011011","00011011",8'h00,8'h00,8'h00,8'h00,
-- 218'h00,8'h7C,"11000110","01100000","00111000","01101100","11000110","11000110","01101100","00111000","00001100","11000110",8'h7C,8'h00,8'h00,8'h00,
-- 228'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'hFE,8'hFE,8'hFE,8'hFE,8'h00,8'h00,8'h00,8'h00,
-- 238'h00,8'h00,"00011000",8'h3C,8'h7E,"00011000","00011000","00011000",8'h7E,8'h3C,"00011000",8'h7E,"00110000",8'h00,8'h00,8'h00,
-- 248'h00,8'h00,"00011000",8'h3C,8'h7E,"00011000","00011000","00011000","00011000","00011000","00011000","00011000",8'h00,8'h00,8'h00,8'h00,
-- 258'h00,8'h00,"00011000","00011000","00011000","00011000","00011000","00011000","00011000",8'h7E,8'h3C,"00011000",8'h00,8'h00,8'h00,8'h00,
-- 268'h00,8'h00,8'h00,8'h00,8'h00,"00011000","00001100",8'hFE,"00001100","00011000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 278'h00,8'h00,8'h00,8'h00,8'h00,"00110000","01100000",8'hFE,"01100000","00110000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 288'h00,8'h00,8'h00,8'h00,8'h00,8'h00,"11000000","11000000","11000000",8'hFE,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 298'h00,8'h00,8'h00,8'h00,8'h00,"00100100","01100110",8'hFF,"01100110","00100100",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 308'h00,8'h00,8'h00,8'h00,"00010000","00111000","00111000",8'h7C,8'h7C,8'hFE,8'hFE,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 318'h00,8'h00,8'h00,8'h00,8'hFE,8'hFE,8'h7C,8'h7C,"00111000","00111000","00010000",8'h00,8'h00,8'h00,8'h00,8'h00,
-- 328'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 338'h00,8'h00,"00011000",8'h3C,8'h3C,8'h3C,"00011000","00011000","00011000",8'h00,"00011000","00011000",8'h00,8'h00,8'h00,8'h00,
-- 348'h00,"01100110","01100110","01100110","00100100",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 358'h00,8'h00,8'h00,"01101100","01101100",8'hFE,"01101100","01101100","01101100",8'hFE,"01101100","01101100",8'h00,8'h00,8'h00,8'h00,
-- 36"00011000","00011000",8'h7C,"11000110","11000010","11000000",8'h7C,"00000110","00000110","10000110","11000110",8'h7C,"00011000","00011000",8'h00,8'h00,
-- 378'h00,8'h00,8'h00,8'h00,"11000010","11000110","00001100","00011000","00110000","01100000","11000110","10000110",8'h00,8'h00,8'h00,8'h00,
-- 388'h00,8'h00,"00111000","01101100","01101100","00111000","01110110","11011100","11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
-- 398'h00,"00110000","00110000","00110000","01100000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 408'h00,8'h00,"00001100","00011000","00110000","00110000","00110000","00110000","00110000","00110000","00011000","00001100",8'h00,8'h00,8'h00,8'h00,
-- 418'h00,8'h00,"00110000","00011000","00001100","00001100","00001100","00001100","00001100","00001100","00011000","00110000",8'h00,8'h00,8'h00,8'h00,
-- 428'h00,8'h00,8'h00,8'h00,8'h00,"01100110",8'h3C,8'hFF,8'h3C,"01100110",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 438'h00,8'h00,8'h00,8'h00,8'h00,"00011000","00011000",8'h7E,"00011000","00011000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 448'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,"00011000","00011000","00011000","00110000",8'h00,8'h00,8'h00,
-- 458'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h7E,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 468'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,"00011000","00011000",8'h00,8'h00,8'h00,8'h00,
-- 478'h00,8'h00,8'h00,8'h00,"00000010","00000110","00001100","00011000","00110000","01100000","11000000","10000000",8'h00,8'h00,8'h00,8'h00,
-- 488'h00,8'h00,8'h7C,"11000110","11000110","11001110","11011110","11110110","11100110","11000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 498'h00,8'h00,"00011000","00111000","01111000","00011000","00011000","00011000","00011000","00011000","00011000",8'h7E,8'h00,8'h00,8'h00,8'h00,
-- 508'h00,8'h00,8'h7C,"11000110","00000110","00001100","00011000","00110000","01100000","11000000","11000110",8'hFE,8'h00,8'h00,8'h00,8'h00,
-- 518'h00,8'h00,8'h7C,"11000110","00000110","00000110",8'h3C,"00000110","00000110","00000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 528'h00,8'h00,"00001100","00011100",8'h3C,"01101100","11001100",8'hFE,"00001100","00001100","00001100","00011110",8'h00,8'h00,8'h00,8'h00,
-- 538'h00,8'h00,8'hFE,"11000000","11000000","11000000","11111100","00000110","00000110","00000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 548'h00,8'h00,"00111000","01100000","11000000","11000000","11111100","11000110","11000110","11000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 558'h00,8'h00,8'hFE,"11000110","00000110","00000110","00001100","00011000","00110000","00110000","00110000","00110000",8'h00,8'h00,8'h00,8'h00,
-- 568'h00,8'h00,8'h7C,"11000110","11000110","11000110",8'h7C,"11000110","11000110","11000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 578'h00,8'h00,8'h7C,"11000110","11000110","11000110",8'h7E,"00000110","00000110","00000110","00001100","01111000",8'h00,8'h00,8'h00,8'h00,
-- 588'h00,8'h00,8'h00,8'h00,"00011000","00011000",8'h00,8'h00,8'h00,"00011000","00011000",8'h00,8'h00,8'h00,8'h00,8'h00,
-- 598'h00,8'h00,8'h00,8'h00,"00011000","00011000",8'h00,8'h00,8'h00,"00011000","00011000","00110000",8'h00,8'h00,8'h00,8'h00,
-- 608'h00,8'h00,8'h00,"00000110","00001100","00011000","00110000","01100000","00110000","00011000","00001100","00000110",8'h00,8'h00,8'h00,8'h00,
-- 618'h00,8'h00,8'h00,8'h00,8'h00,8'h7E,8'h00,8'h00,8'h7E,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 628'h00,8'h00,8'h00,"01100000","00110000","00011000","00001100","00000110","00001100","00011000","00110000","01100000",8'h00,8'h00,8'h00,8'h00,
-- 638'h00,8'h00,8'h7C,"11000110","11000110","00001100","00011000","00011000","00011000",8'h00,"00011000","00011000",8'h00,8'h00,8'h00,8'h00,
-- 648'h00,8'h00,8'h7C,"11000110","11000110","11000110","11011110","11011110","11011110","11011100","11000000",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 658'h00,8'h00,"00010000","00111000","01101100","11000110","11000110",8'hFE,"11000110","11000110","11000110","11000110",8'h00,8'h00,8'h00,8'h00,
-- 668'h00,8'h00,"11111100","01100110","01100110","01100110",8'h7C,"01100110","01100110","01100110","01100110","11111100",8'h00,8'h00,8'h00,8'h00,
-- 678'h00,8'h00,8'h3C,"01100110","11000010","11000000","11000000","11000000","11000000","11000010","01100110",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 688'h00,8'h00,"11111000","01101100","01100110","01100110","01100110","01100110","01100110","01100110","01101100","11111000",8'h00,8'h00,8'h00,8'h00,
-- 698'h00,8'h00,8'hFE,"01100110","01100010","01101000","01111000","01101000","01100000","01100010","01100110",8'hFE,8'h00,8'h00,8'h00,8'h00,
-- 708'h00,8'h00,8'hFE,"01100110","01100010","01101000","01111000","01101000","01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
-- 718'h00,8'h00,8'h3C,"01100110","11000010","11000000","11000000","11011110","11000110","11000110","01100110","00111010",8'h00,8'h00,8'h00,8'h00,
-- 728'h00,8'h00,"11000110","11000110","11000110","11000110",8'hFE,"11000110","11000110","11000110","11000110","11000110",8'h00,8'h00,8'h00,8'h00,
-- 738'h00,8'h00,8'h3C,"00011000","00011000","00011000","00011000","00011000","00011000","00011000","00011000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 748'h00,8'h00,"00011110","00001100","00001100","00001100","00001100","00001100","11001100","11001100","11001100","01111000",8'h00,8'h00,8'h00,8'h00,
-- 758'h00,8'h00,"11100110","01100110","01100110","01101100","01111000","01111000","01101100","01100110","01100110","11100110",8'h00,8'h00,8'h00,8'h00,
-- 768'h00,8'h00,"11110000","01100000","01100000","01100000","01100000","01100000","01100000","01100010","01100110",8'hFE,8'h00,8'h00,8'h00,8'h00,
-- 778'h00,8'h00,8'hC3,"11100111",8'hFF,8'hFF,8'hDB,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'h00,8'h00,8'h00,8'h00,
-- 788'h00,8'h00,"11000110","11100110","11110110",8'hFE,"11011110","11001110","11000110","11000110","11000110","11000110",8'h00,8'h00,8'h00,8'h00,
-- 798'h00,8'h00,8'h7C,"11000110","11000110","11000110","11000110","11000110","11000110","11000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 808'h00,8'h00,"11111100","01100110","01100110","01100110",8'h7C,"01100000","01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
-- 818'h00,8'h00,8'h7C,"11000110","11000110","11000110","11000110","11000110","11000110","11010110","11011110",8'h7C,"00001100",8'h0E,8'h00,8'h00,
-- 828'h00,8'h00,"11111100","01100110","01100110","01100110",8'h7C,"01101100","01100110","01100110","01100110","11100110",8'h00,8'h00,8'h00,8'h00,
-- 838'h00,8'h00,8'h7C,"11000110","11000110","01100000","00111000","00001100","00000110","11000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 848'h00,8'h00,8'hFF,8'hDB,8'h99,"00011000","00011000","00011000","00011000","00011000","00011000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 858'h00,8'h00,"11000110","11000110","11000110","11000110","11000110","11000110","11000110","11000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 868'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,"01100110",8'h3C,"00011000",8'h00,8'h00,8'h00,8'h00,
-- 878'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hC3,8'hC3,8'hDB,8'hDB,8'hFF,"01100110","01100110",8'h00,8'h00,8'h00,8'h00,
-- 888'h00,8'h00,8'hC3,8'hC3,"01100110",8'h3C,"00011000","00011000",8'h3C,"01100110",8'hC3,8'hC3,8'h00,8'h00,8'h00,8'h00,
-- 898'h00,8'h00,8'hC3,8'hC3,8'hC3,"01100110",8'h3C,"00011000","00011000","00011000","00011000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 908'h00,8'h00,8'hFF,8'hC3,"10000110","00001100","00011000","00110000","01100000","11000001",8'hC3,8'hFF,8'h00,8'h00,8'h00,8'h00,
-- 918'h00,8'h00,8'h3C,"00110000","00110000","00110000","00110000","00110000","00110000","00110000","00110000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 928'h00,8'h00,8'h00,"10000000","11000000","11100000","01110000","00111000","00011100",8'h0E,"00000110","00000010",8'h00,8'h00,8'h00,8'h00,
-- 938'h00,8'h00,8'h3C,"00001100","00001100","00001100","00001100","00001100","00001100","00001100","00001100",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 94"00010000","00111000","01101100","11000110",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 958'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'hFF,8'h00,8'h00,
-- 96"00110000","00110000","00011000",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 978'h00,8'h00,8'h00,8'h00,8'h00,"01111000","00001100",8'h7C,"11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
-- 988'h00,8'h00,"11100000","01100000","01100000","01111000","01101100","01100110","01100110","01100110","01100110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 998'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,"11000110","11000000","11000000","11000000","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 1008'h00,8'h00,"00011100","00001100","00001100",8'h3C,"01101100","11001100","11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
-- 1018'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,"11000110",8'hFE,"11000000","11000000","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 1028'h00,8'h00,"00111000","01101100","01100100","01100000","11110000","01100000","01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
-- 1038'h00,8'h00,8'h00,8'h00,8'h00,"01110110","11001100","11001100","11001100","11001100","11001100",8'h7C,"00001100","11001100","01111000",8'h00,
-- 1048'h00,8'h00,"11100000","01100000","01100000","01101100","01110110","01100110","01100110","01100110","01100110","11100110",8'h00,8'h00,8'h00,8'h00,
-- 1058'h00,8'h00,"00011000","00011000",8'h00,"00111000","00011000","00011000","00011000","00011000","00011000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 1068'h00,8'h00,"00000110","00000110",8'h00,8'h0E,"00000110","00000110","00000110","00000110","00000110","00000110","01100110","01100110",8'h3C,8'h00,
-- 1078'h00,8'h00,"11100000","01100000","01100000","01100110","01101100","01111000","01111000","01101100","01100110","11100110",8'h00,8'h00,8'h00,8'h00,
-- 1088'h00,8'h00,"00111000","00011000","00011000","00011000","00011000","00011000","00011000","00011000","00011000",8'h3C,8'h00,8'h00,8'h00,8'h00,
-- 1098'h00,8'h00,8'h00,8'h00,8'h00,"11100110",8'hFF,8'hDB,8'hDB,8'hDB,8'hDB,8'hDB,8'h00,8'h00,8'h00,8'h00,
-- 1108'h00,8'h00,8'h00,8'h00,8'h00,"11011100","01100110","01100110","01100110","01100110","01100110","01100110",8'h00,8'h00,8'h00,8'h00,
-- 1118'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,"11000110","11000110","11000110","11000110","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 1128'h00,8'h00,8'h00,8'h00,8'h00,"11011100","01100110","01100110","01100110","01100110","01100110",8'h7C,"01100000","01100000","11110000",8'h00,
-- 1138'h00,8'h00,8'h00,8'h00,8'h00,"01110110","11001100","11001100","11001100","11001100","11001100",8'h7C,"00001100","00001100","00011110",8'h00,
-- 1148'h00,8'h00,8'h00,8'h00,8'h00,"11011100","01110110","01100110","01100000","01100000","01100000","11110000",8'h00,8'h00,8'h00,8'h00,
-- 1158'h00,8'h00,8'h00,8'h00,8'h00,8'h7C,"11000110","01100000","00111000","00001100","11000110",8'h7C,8'h00,8'h00,8'h00,8'h00,
-- 1168'h00,8'h00,"00010000","00110000","00110000","11111100","00110000","00110000","00110000","00110000","00110110","00011100",8'h00,8'h00,8'h00,8'h00,
-- 1178'h00,8'h00,8'h00,8'h00,8'h00,"11001100","11001100","11001100","11001100","11001100","11001100","01110110",8'h00,8'h00,8'h00,8'h00,
-- 1188'h00,8'h00,8'h00,8'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hC3,"01100110",8'h3C,"00011000",8'h00,8'h00,8'h00,8'h00,
-- 1198'h00,8'h00,8'h00,8'h00,8'h00,8'hC3,8'hC3,8'hC3,8'hDB,8'hDB,8'hFF,"01100110",8'h00,8'h00,8'h00,8'h00,
-- 1208'h00,8'h00,8'h00,8'h00,8'h00,8'hC3,"01100110",8'h3C,"00011000",8'h3C,"01100110",8'hC3,8'h00,8'h00,8'h00,8'h00,
-- 1218'h00,8'h00,8'h00,8'h00,8'h00,"11000110","11000110","11000110","11000110","11000110","11000110",8'h7E,"00000110","00001100","11111000",8'h00,
-- 1228'h00,8'h00,8'h00,8'h00,8'h00,8'hFE,"11001100","00011000","00110000","01100000","11000110",8'hFE,8'h00,8'h00,8'h00,8'h00,
-- 1238'h00,8'h00,8'h0E,"00011000","00011000","00011000","01110000","00011000","00011000","00011000","00011000",8'h0E,8'h00,8'h00,8'h00,8'h00,
-- 1248'h00,8'h00,"00011000","00011000","00011000","00011000",8'h00,"00011000","00011000","00011000","00011000","00011000",8'h00,8'h00,8'h00,8'h00,
-- 1258'h00,8'h00,"01110000","00011000","00011000","00011000",8'h0E,"00011000","00011000","00011000","00011000","01110000",8'h00,8'h00,8'h00,8'h00,
-- 1268'h00,8'h00,"01110110","11011100",8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
-- 1278'h00,8'h00,8'h00,8'h00,"00010000","00111000","01101100","11000110","11000110","11000110",8'hFE,8'h00,8'h00,8'h00,8'h00,8'h00
);

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
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
`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 )
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,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'd4,
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

Binary file not shown.

Binary file not shown.

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,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2010 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
# Version 10.1 Build 153 11/29/2010 SJ Full Version
# Date created = 11:11:11 June 13, 2011
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "10.1"
DATE = "11:11:11 June 13, 2011"
# Revisions
PROJECT_REVISION = "gb"

View File

@@ -0,0 +1,191 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2011 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
# Version 11.0 Build 157 04/27/2011 SJ Full Version
# Date created = 17:14:01 April 10, 2012
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# led_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.
#
# -------------------------------------------------------------------------- #
set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name TOP_LEVEL_ENTITY gb_mist
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 11.0
set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:14:01 APRIL 10, 2012"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP"
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "AS INPUT TRI-STATED"
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
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_location_assignment PIN_7 -to LED
set_location_assignment PIN_22 -to CLOCK_50[0]
set_location_assignment PIN_23 -to CLOCK_50[1]
set_location_assignment PIN_128 -to CLOCK_32[0]
set_location_assignment PIN_129 -to CLOCK_32[1]
set_location_assignment PIN_54 -to CLOCK_27[0]
set_location_assignment PIN_55 -to CLOCK_27[1]
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_46 -to UART_TX
set_location_assignment PIN_31 -to UART_RX
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_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE stp1.stp
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON
set_global_assignment -name FITTER_EFFORT "FAST FIT"
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)"
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
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_*
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
set_global_assignment -name SYSTEMVERILOG_FILE rtl/gb_mist.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/gb.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/lcd.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sprites.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sprite_sort.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sprite.sv
set_global_assignment -name VHDL_FILE rtl/gbc_snd.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/timer.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/zpram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/iram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/scandoubler.sv
set_global_assignment -name VERILOG_FILE rtl/pll.v
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/keyboard.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/data_io.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/dac.sv
set_global_assignment -name VHDL_FILE rtl/BROM.vhd
set_global_assignment -name VHDL_FILE rtl/t80/T80_Reg.vhd
set_global_assignment -name VHDL_FILE rtl/t80/T80_Pack.vhd
set_global_assignment -name VHDL_FILE rtl/t80/T80_MCode.vhd
set_global_assignment -name VHDL_FILE rtl/t80/T80_ALU.vhd
set_global_assignment -name VHDL_FILE rtl/t80/T80.vhd
set_global_assignment -name VHDL_FILE rtl/t80/GBse.vhd
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -0,0 +1,43 @@
---------------------------------------------------------------------------------
--
-- Gameboy Core for MiST by Till Harbaum
-- Changed by Gehstock
-- 19 December 2017
--
---------------------------------------------------------------------------------
-- This is source code of a gameboy implementation for the MIST.
-- It's based on the [t80](http://opencores.com/project,t80) CPU core.
-- A minor
fix was needed for the "LD ($FF00+C)" instruction.
-- The audio implementation has been taken from the PACE framework.
-- The
original file is available in the [pacedev svn]
-- (https://svn.pacedev.net/repos/pace/sw/src/component/sound/gb/gbc_snd.vhd).
---------------------------------------------------------------------------------
--
--
-- Keyboard inputs :
--
-- ESC: : Start
-- TAB: : Select
-- SPACE : Button A
-- LALT : Button B
-- ARROW KEYS : Movements
--
-- Joystick support.
--
---------------------------------------------------------------------------------
ToDo: Mappers

View File

@@ -0,0 +1,56 @@
library ieee;
use ieee.std_logic_1164.all,ieee.numeric_std.all;
entity BROM is
port (
clk : in std_logic;
addr : in std_logic_vector(7 downto 0);
data : out std_logic_vector(7 downto 0)
);
end entity;
architecture prom of BROM is
type ROM_ARRAY is array(0 to 255) of std_logic_vector(7 downto 0);
signal ROM : ROM_ARRAY := (
x"31",x"FE",x"FF",x"AF",x"21",x"FF",x"9F",x"32", -- 0x0000
x"CB",x"7C",x"20",x"FB",x"21",x"26",x"FF",x"0E", -- 0x0008
x"11",x"3E",x"80",x"32",x"E2",x"0C",x"3E",x"F3", -- 0x0010
x"E2",x"32",x"3E",x"77",x"77",x"3E",x"FC",x"E0", -- 0x0018
x"47",x"F0",x"50",x"FE",x"42",x"28",x"75",x"11", -- 0x0020
x"04",x"01",x"21",x"10",x"80",x"1A",x"4F",x"CD", -- 0x0028
x"A0",x"00",x"CD",x"A0",x"00",x"13",x"7B",x"FE", -- 0x0030
x"34",x"20",x"F2",x"11",x"B2",x"00",x"06",x"08", -- 0x0038
x"1A",x"22",x"22",x"13",x"05",x"20",x"F9",x"3E", -- 0x0040
x"19",x"EA",x"10",x"99",x"21",x"2F",x"99",x"0E", -- 0x0048
x"0C",x"3D",x"28",x"08",x"32",x"0D",x"20",x"F9", -- 0x0050
x"2E",x"0F",x"18",x"F3",x"67",x"3E",x"64",x"57", -- 0x0058
x"E0",x"42",x"3E",x"91",x"E0",x"40",x"04",x"1E", -- 0x0060
x"02",x"0E",x"0C",x"F0",x"44",x"FE",x"90",x"20", -- 0x0068
x"FA",x"0D",x"20",x"F7",x"1D",x"20",x"F2",x"0E", -- 0x0070
x"13",x"24",x"7C",x"1E",x"83",x"FE",x"62",x"28", -- 0x0078
x"06",x"1E",x"C1",x"FE",x"64",x"20",x"06",x"7B", -- 0x0080
x"E2",x"0C",x"3E",x"87",x"E2",x"F0",x"42",x"90", -- 0x0088
x"E0",x"42",x"15",x"20",x"D2",x"05",x"20",x"64", -- 0x0090
x"16",x"20",x"18",x"CB",x"E0",x"40",x"18",x"5C", -- 0x0098
x"06",x"04",x"C5",x"CB",x"11",x"17",x"C1",x"CB", -- 0x00A0
x"11",x"17",x"05",x"20",x"F5",x"22",x"22",x"22", -- 0x00A8
x"22",x"C9",x"3C",x"42",x"A5",x"81",x"A5",x"99", -- 0x00B0
x"42",x"3C",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00B8
x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00C0
x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00C8
x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00D0
x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00D8
x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00E0
x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00E8
x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF", -- 0x00F0
x"FF",x"FF",x"FF",x"FF",x"3E",x"01",x"E0",x"50" -- 0x00F8
);
begin
process(clk)
begin
if rising_edge(clk) then
data <= ROM (to_integer(unsigned(addr)));
end if;
end process;
end architecture;

View File

@@ -0,0 +1,2 @@
`define BUILD_DATE "171221"
`define BUILD_TIME "172231"

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.sv"
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,33 @@
//
// PWM DAC
//
// MSBI is the highest bit number. NOT amount of bits!
//
module dac #(parameter MSBI=15, parameter INV=1'b1)
(
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 <= INV;
end else begin
SigmaLatch <= SigmaAdder;
DACout <= SigmaLatch[MSBI+2] ^ INV;
end
end
endmodule

View File

@@ -0,0 +1,118 @@
//
// data_io.v
//
// io controller writable ram for the MiST board
// https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module data_io (
// io controller spi interface
input sck,
input ss,
input sdi,
output downloading, // signal indicating an active download
output reg [4:0] index, // menu index used to upload the file
// external ram interface
input clk,
output reg wr,
output reg [23:0] addr,
output reg [15:0] data
);
// *********************************************************************************
// spi client
// *********************************************************************************
// this core supports only the display related OSD commands
// of the minimig
reg [14:0] sbuf;
reg [7:0] cmd;
reg [4:0] cnt;
reg rclk;
reg [23:0] laddr;
reg [15:0] ldata;
localparam UIO_FILE_TX = 8'h53;
localparam UIO_FILE_TX_DAT = 8'h54;
localparam UIO_FILE_INDEX = 8'h55;
assign downloading = downloading_reg;
reg downloading_reg = 1'b0;
// data_io has its own SPI interface to the io controller
always@(posedge sck, posedge ss) begin
if(ss == 1'b1)
cnt <= 5'd0;
else begin
rclk <= 1'b0;
// don't shift in last bit. It is evaluated directly
// when writing to ram
if(cnt != 23)
sbuf <= { sbuf[13:0], sdi};
// count 0-7 8-15 16-23 8-15 16-23 ...
if(cnt < 23) cnt <= cnt + 4'd1;
else cnt <= 4'd8;
// finished command byte
if(cnt == 7)
cmd <= {sbuf[6:0], sdi};
// prepare/end transmission
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
// prepare
if(sdi) begin
// download rom to address 0
laddr <= 24'h0 - 24'd1;
downloading_reg <= 1'b1;
end else
downloading_reg <= 1'b0;
end
// command 0x54: UIO_FILE_TX
if((cmd == UIO_FILE_TX_DAT) && (cnt == 23)) begin
ldata <= {sbuf, sdi};
laddr <= laddr + 24'd1;
rclk <= 1'b1;
end
// expose file (menu) index
if((cmd == UIO_FILE_INDEX) && (cnt == 15))
index <= {sbuf[3:0], sdi};
end
end
reg rclkD, rclkD2;
always@(posedge clk) begin
// bring all signals from spi clock domain into local clock domain
rclkD <= rclk;
rclkD2 <= rclkD;
wr <= 1'b0;
if(rclkD && !rclkD2) begin
addr <= laddr;
data <= ldata;
wr <= 1'b1;
end
end
endmodule

View File

@@ -0,0 +1,359 @@
//
// gb.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module gb (
input reset,
input clk,
input fast_boot,
input [7:0] joystick,
// cartridge interface
// can adress up to 1MB ROM
output [15:0] cart_addr,
output cart_rd,
output cart_wr,
input [7:0] cart_do,
output [7:0] cart_di,
// audio
output [15:0] audio_l,
output [15:0] audio_r,
// lcd interface
output lcd_clkena,
output [1:0] lcd_data,
output [1:0] lcd_mode,
output lcd_on
);
// include cpu
wire [15:0] cpu_addr;
wire [7:0] cpu_do;
wire sel_timer = (cpu_addr[15:4] == 12'hff0) && (cpu_addr[3:2] == 2'b01);
wire sel_video_reg = cpu_addr[15:4] == 12'hff4;
wire sel_video_oam = cpu_addr[15:8] == 8'hfe;
wire sel_joy = cpu_addr == 16'hff00; // joystick controller
wire sel_rom = !cpu_addr[15]; // lower 32k are rom
wire sel_cram = cpu_addr[15:13] == 3'b101; // 8k cart ram at $a000
wire sel_vram = cpu_addr[15:13] == 3'b100; // 8k video ram at $8000
wire sel_ie = cpu_addr == 16'hffff; // interupt enable
wire sel_if = cpu_addr == 16'hff0f; // interupt flag
wire sel_iram = (cpu_addr[15:14] == 2'b11) && (cpu_addr[15:8] != 8'hff); // 8k internal ram at $c000
wire sel_zpram = (cpu_addr[15:7] == 9'b111111111) && // 127 bytes zero pageram at $ff80
(cpu_addr != 16'hffff);
wire sel_audio = (cpu_addr[15:8] == 8'hff) && // audio reg ff10 - ff3f
((cpu_addr[7:5] == 3'b001) || (cpu_addr[7:4] == 4'b0001));
// the boot roms sees a special $42 flag in $ff50 if it's supposed to to a fast boot
wire sel_fast = fast_boot && cpu_addr == 16'hff50 && boot_rom_enabled;
// http://gameboy.mongenel.com/dmg/asmmemmap.html
wire [7:0] cpu_di =
irq_ack?irq_vec:
sel_fast?8'h42: // fast boot flag
sel_joy?joy_do: // joystick register
sel_timer?timer_do: // timer registers
sel_video_reg?video_do: // video registers
sel_video_oam?video_do: // video object attribute memory
sel_audio?audio_do: // audio registers
sel_rom?rom_do: // boot rom + cartridge rom
sel_cram?rom_do: // cartridge ram
sel_vram?vram_do: // vram
sel_zpram?zpram_do: // zero page ram
sel_iram?iram_do: // internal ram
sel_ie?{3'b000, ie_r}: // interrupt enable register
sel_if?{3'b000, if_r}: // interrupt flag register
8'hff;
wire cpu_wr_n;
wire cpu_rd_n;
wire cpu_iorq_n;
wire cpu_m1_n;
wire cpu_mreq_n;
GBse cpu (
.RESET_n ( !reset ),
.CLK_n ( clk ),
.CLKEN ( 1'b1 ),
.WAIT_n ( 1'b1 ),
.INT_n ( irq_n ),
.NMI_n ( 1'b1 ),
.BUSRQ_n ( 1'b1 ),
.M1_n ( cpu_m1_n ),
.MREQ_n ( cpu_mreq_n ),
.IORQ_n ( cpu_iorq_n ),
.RD_n ( cpu_rd_n ),
.WR_n ( cpu_wr_n ),
.RFSH_n ( ),
.HALT_n ( ),
.BUSAK_n ( ),
.A ( cpu_addr ),
.DI ( cpu_di ),
.DO ( cpu_do )
);
// --------------------------------------------------------------------
// ------------------------------ audio -------------------------------
// --------------------------------------------------------------------
wire audio_rd = !cpu_rd_n && sel_audio;
wire audio_wr = !cpu_wr_n && sel_audio;
wire [7:0] audio_do;
gbc_snd audio (
.clk ( clk ),
.reset ( reset ),
.s1_read ( audio_rd ),
.s1_write ( audio_wr ),
.s1_addr ( cpu_addr[5:0] ),
.s1_readdata ( audio_do ),
.s1_writedata ( cpu_do ),
.snd_left ( audio_l ),
.snd_right ( audio_r )
);
// --------------------------------------------------------------------
// ------------------------------ inputs ------------------------------
// --------------------------------------------------------------------
wire [3:0] joy_p4 = { !joystick[2], !joystick[3], !joystick[1], !joystick[0] };
wire [3:0] joy_p5 = { !joystick[7], !joystick[6], !joystick[5], !joystick[4] };
reg [1:0] p54;
always @(posedge clk) begin
if(reset)
p54 <= 2'b11;
else if(sel_joy && !cpu_wr_n)
p54 <= cpu_do[5:4];
end
wire [7:0] joy_do = { 2'b11, p54,
((!p54[0])?joy_p4:4'hf) & ((!p54[1])?joy_p5:4'hf) };
// --------------------------------------------------------------------
// ---------------------------- interrupts ----------------------------
// --------------------------------------------------------------------
// interrupt flags are set when the event happens or when the cpu writes
// the register to 1. The "highest" one active is cleared when the cpu
// runs an interrupt ack cycle or when it writes a 0 to the register
wire irq_ack = !cpu_iorq_n && !cpu_m1_n;
// latch irq vector at the begin of the irq ack
reg [7:0] irq_vec;
always @(posedge irq_ack)
irq_vec <=
if_r[0]?8'h40: // vsync
if_r[1]?8'h48: // lcdc
if_r[2]?8'h50: // timer
if_r[3]?8'h58: // serial
if_r[4]?8'h60: // input
8'h55;
wire vs = (lcd_mode == 2'b01);
reg vsD, vsD2;
reg [3:0] inputD, inputD2;
// irq is low when an enable irq is active
wire irq_n = !(ie_r & if_r);
reg [4:0] if_r;
reg [4:0] ie_r; // writing $ffff sets the irq enable mask
always @(posedge clk) begin
if(reset) begin
ie_r <= 5'h00;
if_r <= 5'h00;
end
// rising edge on vs
vsD <= vs;
vsD2 <= vsD;
if(vsD && !vsD2) if_r[0] <= 1'b1;
// video irq already is a 1 clock event
if(video_irq) if_r[1] <= 1'b1;
// timer_irq already is a 1 clock event
if(timer_irq) if_r[2] <= 1'b1;
// falling edge on any input line P10..P13
inputD <= joy_p4 | joy_p5;
inputD2 <= inputD;
if(~inputD & inputD2) if_r[4] <= 1'b1;
// cpu acknowledges irq. this clears the active irq with hte
// highest priority
if(irq_ack) begin
if(if_r[0] && ie_r[0]) if_r[0] <= 1'b0;
else if(if_r[1] && ie_r[1]) if_r[1] <= 1'b0;
else if(if_r[2] && ie_r[2]) if_r[2] <= 1'b0;
else if(if_r[3] && ie_r[3]) if_r[3] <= 1'b0;
else if(if_r[4] && ie_r[4]) if_r[4] <= 1'b0;
end
// cpu writes interrupt enable register
if(sel_ie && !cpu_wr_n)
ie_r <= cpu_do[4:0];
// cpu writes interrupt flag register
if(sel_if && !cpu_wr_n)
if_r <= cpu_do[4:0];
end
// --------------------------------------------------------------------
// ------------------------------ timer -------------------------------
// --------------------------------------------------------------------
wire timer_irq;
wire [7:0] timer_do;
timer timer (
.reset ( reset ),
.clk ( clk ),
.irq ( timer_irq ),
.cpu_sel ( sel_timer ),
.cpu_addr ( cpu_addr[1:0] ),
.cpu_wr ( !cpu_wr_n ),
.cpu_di ( cpu_do ),
.cpu_do ( timer_do )
);
// --------------------------------------------------------------------
// ------------------------------ video -------------------------------
// --------------------------------------------------------------------
// cpu tries to read or write the lcd controller registers
wire video_irq;
wire [7:0] video_do;
wire [12:0] video_addr;
wire [15:0] dma_addr;
wire video_rd, dma_rd;
wire [7:0] dma_data = (dma_addr[15:14]==2'b11)?iram_do:cart_do;
video video (
.reset ( reset ),
.clk ( clk ),
.irq ( video_irq ),
.cpu_sel_reg ( sel_video_reg ),
.cpu_sel_oam ( sel_video_oam ),
.cpu_addr ( cpu_addr[7:0] ),
.cpu_wr ( !cpu_wr_n ),
.cpu_di ( cpu_do ),
.cpu_do ( video_do ),
.lcd_on ( lcd_on ),
.lcd_clkena ( lcd_clkena ),
.lcd_data ( lcd_data ),
.mode ( lcd_mode ),
.vram_rd ( video_rd ),
.vram_addr ( video_addr ),
.vram_data ( vram_do ),
.dma_rd ( dma_rd ),
.dma_addr ( dma_addr ),
.dma_data ( dma_data )
);
// total 8k vram from $8000 to $9fff
wire cpu_wr_vram = sel_vram && !cpu_wr_n;
wire [7:0] vram_do;
wire vram_wren = video_rd?1'b0:cpu_wr_vram;
wire [12:0] vram_addr = video_rd?video_addr:cpu_addr[12:0];
vram vram (
.clock ( clk ),
.address ( vram_addr ),
.wren ( vram_wren ),
.data ( cpu_do ),
.q ( vram_do )
);
// --------------------------------------------------------------------
// -------------------------- zero page ram ---------------------------
// --------------------------------------------------------------------
// 127 bytes internal zero page ram from $ff80 to $fffe
wire cpu_wr_zpram = sel_zpram && !cpu_wr_n;
wire [7:0] zpram_do;
zpram zpram (
.clock ( clk ),
.address ( cpu_addr[6:0] ),
.wren ( cpu_wr_zpram ),
.data ( cpu_do ),
.q ( zpram_do )
);
// --------------------------------------------------------------------
// ------------------------- 8k internal ram --------------------------
// --------------------------------------------------------------------
wire iram_wren = dma_rd?1'b0:cpu_wr_iram;
wire [12:0] iram_addr = dma_rd?dma_addr[12:0]:cpu_addr[12:0];
wire cpu_wr_iram = sel_iram && !cpu_wr_n;
wire [7:0] iram_do;
iram iram (
.clock ( clk ),
.address ( iram_addr[12:0]),
.wren ( iram_wren ),
.data ( cpu_do ),
.q ( iram_do )
);
// --------------------------------------------------------------------
// ------------------------ internal boot rom -------------------------
// --------------------------------------------------------------------
// writing 01 to $ff50 disables the internal rom
reg boot_rom_enabled;
always @(posedge clk) begin
if(reset)
boot_rom_enabled <= 1'b1;
else if((cpu_addr == 16'hff50) && !cpu_wr_n && cpu_do[0])
boot_rom_enabled <= 1'b0;
end
// combine boot rom data with cartridge data
wire [7:0] rom_do = ((cpu_addr[14:8] == 7'h00) && boot_rom_enabled)?boot_rom_do:cart_do;
assign cart_di = cpu_do;
assign cart_addr = dma_rd?dma_addr:cpu_addr;
assign cart_rd = dma_rd || ((sel_rom || sel_cram) && !cpu_rd_n);
assign cart_wr = (sel_rom || sel_cram) && !cpu_wr_n;
wire [7:0] boot_rom_do;
BROM BROM (
.addr ( cpu_addr[7:0] ),
.clk ( clk ),
.data ( boot_rom_do )
);
endmodule

View File

@@ -0,0 +1,439 @@
//
// gb_mist.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module gb_mist (
input [1:0] CLOCK_27,
output LED,
// SPI interface to arm io controller
output SPI_DO,
input SPI_DI,
input SPI_SCK,
input SPI_SS2,
input SPI_SS3,
input SPI_SS4,
input CONF_DATA0,
// SDRAM interface
inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits
output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits
output SDRAM_DQML, // SDRAM Low-byte Data Mask
output SDRAM_DQMH, // SDRAM High-byte Data Mask
output SDRAM_nWE, // SDRAM Write Enable
output SDRAM_nCAS, // SDRAM Column Address Strobe
output SDRAM_nRAS, // SDRAM Row Address Strobe
output SDRAM_nCS, // SDRAM Chip Select
output [1:0] SDRAM_BA, // SDRAM Bank Address
output SDRAM_CLK, // SDRAM Clock
output SDRAM_CKE, // SDRAM Clock Enable
// audio
output AUDIO_L,
output AUDIO_R,
// video
output VGA_HS,
output VGA_VS,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B
);
assign LED = !dio_download;
`include "rtl/build_id.sv"
localparam CONF_STR = {
"GAMEBOY;GBCSGB;",
"F,GB;",
"O12,LCD ,white,yellow,invert;",
"O3,Boot,Normal,Fast;",
"O45,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
"O6,Mapper,Detect,Force MBC1;",
"T7,Reset;",
"V,v1.00.",`BUILD_DATE
};
wire clk32;
reg clk4; // 4.194304 MHz CPU clock and GB pixel clock
reg clk8; // 8.388608 MHz VGA pixel clock
reg clk16; // 16.777216 MHz
wire pll_locked;
wire reset = (reset_cnt != 0);
reg [9:0] reset_cnt;
wire [31:0] status;
wire [1:0] buttons, switches;
wire [7:0] kbjoy;
wire [7:0] joy_0, joy_1;
wire scandoubler_disable;
wire ypbpr;
wire ps2_kbd_clk, ps2_kbd_data;
wire hs, vs;
wire [5:0] r,g,b;
wire [15:0] audio_left;
wire [15:0] audio_right;
wire [7:0] cart_di; // data from cpu to cart
wire [7:0] cart_do = cart_addr[0]?sdram_do[7:0]:sdram_do[15:8];
wire [15:0] cart_addr;
wire cart_rd;
wire cart_wr;
reg eject = 1'b0;
wire lcd_clkena;
wire [1:0] lcd_data;
wire [1:0] lcd_mode;
wire lcd_on;
wire invert;
wire color;
// TODO: ds for cart ram write
wire [1:0] sdram_ds = dio_download?2'b11:{!cart_addr[0], cart_addr[0]};
wire [15:0] sdram_do;
wire [15:0] sdram_di = dio_download?dio_data:{cart_di, cart_di};
wire [23:0] sdram_addr = dio_download?dio_addr:{3'b000, mbc_bank, cart_addr[12:1]};
wire sdram_oe = !dio_download && cart_rd;
wire sdram_we = (dio_download && dio_write) || (!dio_download && cart_ram_wr);
assign SDRAM_CKE = 1'b1;
wire dio_download;
wire [23:0] dio_addr;
wire [15:0] dio_data;
wire dio_write;
pll pll (
.inclk0(CLOCK_27),
.c0(clk32), // 33.557143 MHz
.c1(SDRAM_CLK), // 33.557143 Mhz phase shifted
.locked(pll_locked)
);
always @(posedge clk8)
clk4 <= !clk4;
always @(posedge clk16)
clk8 <= !clk8;
always @(posedge clk32)
clk16 <= !clk16;
always @(posedge clk4) begin
if(status[0] || status[7] || buttons[1] || !pll_locked || dio_download)
reset_cnt <= 10'd1023;
else
if(reset_cnt != 0)
reset_cnt <= reset_cnt - 10'd1;
end
gb gb (
.reset ( reset ),
.clk ( clk4 ),
.fast_boot ( status[3] ),
.joystick ( joy0 | joy_1 | kbjoy),
.cart_addr ( cart_addr ),
.cart_rd ( cart_rd ),
.cart_wr ( cart_wr ),
.cart_do ( cart_do ),
.cart_di ( cart_di ),
.audio_l ( audio_left ),
.audio_r ( audio_right ),
.lcd_clkena ( lcd_clkena ),
.lcd_data ( lcd_data ),
.lcd_mode ( lcd_mode ),
.lcd_on ( lcd_on )
);
dac dacL(
.CLK ( clk32 ),
.RESET ( reset ),
.DACin ( audio_left[15:1] ),
.DACout ( AUDIO_L )
);
dac dacR(
.CLK ( clk32 ),
.RESET ( reset ),
.DACin ( audio_right[15:1] ),
.DACout ( AUDIO_R )
);
lcd lcd (
.pclk ( clk8 ),
.clk ( clk4 ),
.tint ( status[2:1] == 1 ? 1 : 0 ),
.inv ( status[2:1] == 2 ? 1 : 0 ),
.clkena ( lcd_clkena),
.data ( lcd_data ),
.mode ( lcd_mode ), // used to detect begin of new lines and frames
.on ( lcd_on ),
.hs ( hs ),
.vs ( vs ),
.r ( r ),
.g ( g ),
.b ( b )
);
mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io
(
.clk_sys (clk32 ),
.conf_str (CONF_STR ),
.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 ),
.ps2_kbd_clk (ps2_kbd_clk ),
.ps2_kbd_data (ps2_kbd_data ),
.joystick_0 (joy_0 ),
.joystick_1 (joy_1 ),
.status (status )
);
sdram sdram (
.sd_data (SDRAM_DQ ),
.sd_addr (SDRAM_A ),
.sd_dqm ({SDRAM_DQMH, SDRAM_DQML} ),
.sd_cs (SDRAM_nCS ),
.sd_ba (SDRAM_BA ),
.sd_we (SDRAM_nWE ),
.sd_ras (SDRAM_nRAS ),
.sd_cas (SDRAM_nCAS ),
.clk (clk32 ),
.clkref (clk4 ),
.init (!pll_locked | eject ),
.din (sdram_di ),
.addr (sdram_addr ),
.ds (sdram_ds ),
.we (sdram_we ),
.oe (sdram_oe ),
.dout (sdram_do )
);
// include ROM download helper
data_io data_io (
.sck (SPI_SCK ),
.ss ( SPI_SS2 ),
.sdi ( SPI_DI ),
.downloading ( dio_download ),
.clk ( clk4 ),
.wr ( dio_write ),
.addr ( dio_addr ),
.data ( dio_data )
);
video_mixer #(.LINE_LENGTH(640), .HALF_DEPTH(0)) video_mixer
(
.clk_sys (clk32 ),
.ce_pix (clk16 ),
.ce_pix_actual (clk16 ),
.SPI_SCK (SPI_SCK ),
.SPI_SS3 (SPI_SS3 ),
.SPI_DI (SPI_DI ),
.R (r ),
.G (g ),
.B (b ),
.HSync (hs ),
.VSync (vs ),
.VGA_R (VGA_R ),
.VGA_G (VGA_G ),
.VGA_B (VGA_B ),
.VGA_VS (VGA_VS ),
.VGA_HS (VGA_HS ),
.scandoubler_disable(1 ),//(scandoubler_disable), //VGA Only
.scanlines(scandoubler_disable ? 2'b00 : {status[5:4] == 3, status[5:4] == 2}),
.hq2x (status[5:4]==1),
.ypbpr_full (1 ),
.line_start (0 ),
.mono (0 )
);
keyboard keyboard(
.clk(clk32),
.reset(),
.ps2_kbd_clk(ps2_kbd_clk),
.ps2_kbd_data(ps2_kbd_data),
.joystick(kbjoy)
);
// TODO: RAM bank
// http://fms.komkon.org/GameBoy/Tech/Carts.html
// 32MB SDRAM memory map using word addresses
// 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 D
// 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 S
// -------------------------------------------------
// 0 0 0 0 X X X X X X X X X X X X X X X X X X X X X up to 2MB used as ROM
// 0 0 0 1 X X X X X X X X X X X X X X X X X X X X X up to 2MB used as RAM
// 0 0 0 0 R R B B B B B C C C C C C C C C C C C C C MBC1 ROM (R=RAM bank in mode 0)
// 0 0 0 1 0 0 0 0 0 0 R R C C C C C C C C C C C C C MBC1 RAM (R=RAM bank in mode 1)
// ---------------------------------------------------------------
// ----------------------------- MBC1 ----------------------------
// ---------------------------------------------------------------
wire [8:0] mbc1_addr =
(cart_addr[15:14] == 2'b00)?{8'b000000000, cart_addr[13]}: // 16k ROM Bank 0
(cart_addr[15:14] == 2'b01)?{1'b0, mbc1_rom_bank, cart_addr[13]}: // 16k ROM Bank 1-127
(cart_addr[15:13] == 3'b101)?{7'b1000000, mbc1_ram_bank}: // 8k RAM Bank 0-3
9'd0;
wire [8:0] mbc2_addr =
(cart_addr[15:14] == 2'b00)?{8'b000000000, cart_addr[13]}: // 16k ROM Bank 0
(cart_addr[15:14] == 2'b01)?{1'b0, mbc2_rom_bank, cart_addr[13]}: // 16k ROM Bank 1-15
//todo // 512x4bits RAM, built-in into the MBC2 chip (Read/Write)
9'd0;
// -------------------------- RAM banking ------------------------
// in mode 0 (16/8 mode) the ram is not banked
// in mode 1 (4/32 mode) four ram banks are used
wire [1:0] mbc1_ram_bank = (mbc1_mode ? mbc1_ram_bank_reg:2'b00) & ram_mask;
wire [1:0] mbc2_ram_bank = (mbc2_mode ? mbc2_ram_bank_reg:2'b00) & ram_mask;//todo
// -------------------------- ROM banking ------------------------
// in mode 0 (16/8 mode) the ram bank select signals are the upper rom address lines
// in mode 1 (4/32 mode) the upper two rom address lines are 2'b00
wire [6:0] mbc1_rom_bank_mode = { mbc1_mode?2'b00:mbc1_ram_bank_reg, mbc1_rom_bank_reg};
wire [6:0] mbc2_rom_bank_mode = { mbc2_mode?2'b00:mbc2_ram_bank_reg, mbc2_rom_bank_reg};//todo
// mask address lines to enable proper mirroring
wire [6:0] mbc1_rom_bank = mbc1_rom_bank_mode & rom_mask;//128
wire [6:0] mbc2_rom_bank = mbc2_rom_bank_mode & rom_mask;//16
// --------------------- CPU register interface ------------------
reg mbc1_ram_enable;
reg mbc1_mode;
reg [4:0] mbc1_rom_bank_reg;
reg [1:0] mbc1_ram_bank_reg;
reg mbc2_ram_enable;
reg mbc2_mode;
reg [4:0] mbc2_rom_bank_reg;//todo
reg [1:0] mbc2_ram_bank_reg;//todo
// MBC2 todo
always @(posedge clk4) begin
if(reset) begin
mbc1_rom_bank_reg <= 5'd1;
mbc1_ram_bank_reg <= 2'd0;
mbc1_ram_enable <= 1'b0;
mbc1_mode <= 1'b0;
end else begin
if(cart_wr && (cart_addr[15:13] == 3'b000))
mbc1_ram_enable <= (cart_di[3:0] == 4'ha);
if(cart_wr && (cart_addr[15:13] == 3'b001)) begin
if(cart_di[4:0]==0) mbc1_rom_bank_reg <= 5'd1;
else mbc1_rom_bank_reg <= cart_di[4:0];
end
if(cart_wr && (cart_addr[15:13] == 3'b010))
mbc1_ram_bank_reg <= cart_di[1:0];
if(cart_wr && (cart_addr[15:13] == 3'b011))
mbc1_mode <= cart_di[0];
end
// eject <= status[8];
end
// extract header fields extracted from cartridge
// during download
reg [7:0] cart_mbc_type;
reg [7:0] cart_rom_size;
reg [7:0] cart_ram_size;
reg [7:0] cgb_flag;//$80 = GBC but GB compatible, $C0 GBC Only, $00 or other = GB
reg [7:0] sgb_flag;//GB/SGB Indicator (00 = GameBoy, 03 = Super GameBoy functions)
//(Super GameBoy functions won't work if <> $03.)
// only write sdram if the write attept comes from the cart ram area
wire cart_ram_wr = cart_wr && mbc1_ram_enable && (cart_addr[15:13] == 3'b101);
// RAM size - todo
wire [1:0] ram_mask = // 0 - no ram
(cart_ram_size == 1)?2'b00: // 1 - 2k, 1 bank
(cart_ram_size == 2)?2'b00: // 2 - 8k, 1 bank
2'b11; // 3 - 32k, 4 banks
// 4 - 128k, ?? banks
// 5 - 64k, ?? banks
// ROM size
wire [6:0] rom_mask = // 0 - 2 banks, 32k direct mapped
(cart_rom_size == 1)?7'b0000011: // 1 - 4 banks = 64k
(cart_rom_size == 2)?7'b0000111: // 2 - 8 banks = 128k
(cart_rom_size == 3)?7'b0001111: // 3 - 16 banks = 256k
(cart_rom_size == 4)?7'b0011111: // 4 - 32 banks = 512k
(cart_rom_size == 5)?7'b0111111: // 5 - 64 banks = 1M
(cart_rom_size == 6)?7'b1111111: // 6 - 128 banks = 2M
//? (cart_rom_size == 6)?7'b1111111: // 7 - ??? banks = 4M
//? (cart_rom_size == 6)?7'b1111111: // 8 - ??? banks = 8M
(cart_rom_size == 82)?7'b1000111: //$52 - 72 banks = 1.1M
(cart_rom_size == 83)?7'b1001111: //$53 - 80 banks = 1.2M
// (cart_rom_size == 84)?7'b1011111:
7'b1011111; //$54 - 96 banks = 1.5M
wire mbc1 = (cart_mbc_type == 1) || (cart_mbc_type == 2) || (cart_mbc_type == 3) || ~status[6];
wire mbc2 = (cart_mbc_type == 5) || (cart_mbc_type == 6);
wire mmm01 = (cart_mbc_type == 11) || (cart_mbc_type == 12) || (cart_mbc_type == 13) || (cart_mbc_type == 14);
wire mbc3 = (cart_mbc_type == 15) || (cart_mbc_type == 16) || (cart_mbc_type == 17) || (cart_mbc_type == 18) || (cart_mbc_type == 19);
wire mbc4 = (cart_mbc_type == 21) || (cart_mbc_type == 22) || (cart_mbc_type == 23);
wire mbc5 = (cart_mbc_type == 25) || (cart_mbc_type == 26) || (cart_mbc_type == 27) || (cart_mbc_type == 28) || (cart_mbc_type == 29) || (cart_mbc_type == 30);
wire tama5 = (cart_mbc_type == 253);
//wire tama6 = (cart_mbc_type == ???);
wire HuC1 = (cart_mbc_type == 254);
wire HuC3 = (cart_mbc_type == 255);
wire [8:0] mbc_bank =
mbc1?mbc1_addr: // MBC1, 16k bank 0, 16k bank 1-127 + ram
mbc2?mbc2_addr: // MBC2, 16k bank 0, 16k bank 1-15 + ram
// mbc3?mbc3_addr:
// mbc4?mbc4_addr:
// mbc5?mbc5_addr:
// tama5?tama5_addr:
// HuC1?HuC1_addr:
// HuC3?HuC3_addr:
{7'b0000000, cart_addr[14:13]}; // no MBC, 32k linear address
always @(posedge clk4) begin
if(!pll_locked) begin
cart_mbc_type <= 8'h00;
cart_rom_size <= 8'h00;
cart_ram_size <= 8'h00;
end else begin
if(dio_download && dio_write) begin
// cart is stored in 16 bit wide sdram, so addresses are shifted right
case(dio_addr)
24'h9f: cgb_flag <= dio_data[7:0]; // $143
24'ha2: sgb_flag <= dio_data[7:0]; // $146
24'ha3: cart_mbc_type <= dio_data[7:0]; // $147
24'ha4: { cart_rom_size, cart_ram_size } <= dio_data; // $148/$149
endcase
end
end
end
endmodule

View File

@@ -0,0 +1,935 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
library work;
entity gbc_snd is
generic
(
CLK_FREQ : integer := 100000000
);
port
(
clk : in std_logic;
reset : in std_logic;
s1_read : in std_logic;
s1_write : in std_logic;
s1_addr : in std_logic_vector(5 downto 0);
s1_readdata : out std_logic_vector(7 downto 0);
s1_writedata : in std_logic_vector(7 downto 0);
snd_left : out std_logic_vector(15 downto 0);
snd_right : out std_logic_vector(15 downto 0)
);
end gbc_snd;
architecture SYN of gbc_snd is
subtype wav_t is std_logic_vector(3 downto 0);
type wav_arr_t is array(0 to 31) of wav_t;
--constant clk_freq : integer := 100000000;
constant snd_freq : integer := 4194304;
signal en_snd : boolean; -- Enable at base sound frequency (4.19MHz)
signal en_snd2 : boolean; -- Enable at clk/2
signal en_snd4 : boolean; -- Enable at clk/4
signal en_512 : boolean; -- 512Hz enable
signal en_snden2 : boolean; -- Enable at clk/2
signal en_snden4 : boolean; -- Enable at clk/4
signal en_len : boolean; -- Sample length
signal en_env : boolean; -- Envelope
signal en_sweep : boolean; -- Sweep
signal snd_enable : std_logic;
signal sq1_swper : std_logic_vector(2 downto 0); -- Sq1 sweep period
signal sq1_swdir : std_logic; -- Sq1 sweep direction
signal sq1_swshift : std_logic_vector(2 downto 0); -- Sq1 sweep frequency shift
signal sq1_duty : std_logic_vector(1 downto 0); -- Sq1 duty cycle
signal sq1_slen : std_logic_vector(5 downto 0); -- Sq1 play length
signal sq1_svol : std_logic_vector(3 downto 0); -- Sq1 initial volume
signal sq1_envsgn : std_logic; -- Sq1 envelope sign
signal sq1_envper : std_logic_vector(2 downto 0); -- Sq1 envelope period
signal sq1_freq : std_logic_vector(10 downto 0); -- Sq1 frequency
signal sq1_trigger : std_logic; -- Sq1 trigger play note
signal sq1_lenchk : std_logic; -- Sq1 length check enable
signal sq1_fr2 : std_logic_vector(10 downto 0); -- Sq1 frequency (shadow copy)
signal sq1_vol : std_logic_vector(3 downto 0); -- Sq1 initial volume
signal sq1_playing : std_logic; -- Sq1 channel active
signal sq1_wav : std_logic_vector(5 downto 0); -- Sq1 output waveform
signal sq2_duty : std_logic_vector(1 downto 0); -- Sq2 duty cycle
signal sq2_slen : std_logic_vector(5 downto 0); -- Sq2 play length
signal sq2_svol : std_logic_vector(3 downto 0); -- Sq2 initial volume
signal sq2_envsgn : std_logic; -- Sq2 envelope sign
signal sq2_envper : std_logic_vector(2 downto 0); -- Sq2 envelope period
signal sq2_freq : std_logic_vector(10 downto 0); -- Sq2 frequency
signal sq2_trigger : std_logic; -- Sq2 trigger play note
signal sq2_lenchk : std_logic; -- Sq2 length check enable
signal sq2_fr2 : std_logic_vector(10 downto 0); -- Sq2 frequency (shadow copy)
signal sq2_vol : std_logic_vector(3 downto 0); -- Sq2 initial volume
signal sq2_playing : std_logic; -- Sq2 channel active
signal sq2_wav : std_logic_vector(5 downto 0); -- Sq2 output waveform
signal wav_enable : std_logic; -- Wave enable
signal wav_slen : std_logic_vector(7 downto 0); -- Wave play length
signal wav_volsh : std_logic_vector(1 downto 0); -- Wave volume shift
signal wav_freq : std_logic_vector(10 downto 0); -- Wave frequency
signal wav_trigger : std_logic; -- Wave trigger play note
signal wav_lenchk : std_logic; -- Wave length check enable
signal wav_fr2 : std_logic_vector(10 downto 0); -- Wave frequency (shadow copy)
signal wav_playing : std_logic;
signal wav_wav : std_logic_vector(5 downto 0); -- Wave output waveform
signal wav_ram : wav_arr_t; -- Wave table
signal wav_shift : boolean;
signal noi_slen : std_logic_vector(5 downto 0);
signal noi_svol : std_logic_vector(3 downto 0);
signal noi_envsgn : std_logic;
signal noi_envper : std_logic_vector(2 downto 0);
signal noi_freqsh : std_logic_vector(3 downto 0);
signal noi_short : std_logic;
signal noi_div : std_logic_vector(2 downto 0);
signal noi_trigger : std_logic;
signal noi_lenchk : std_logic;
signal noi_fr2 : std_logic_vector(10 downto 0); -- Noise frequency (shadow copy)
signal noi_vol : std_logic_vector(3 downto 0); -- Noise initial volume
signal noi_playing : std_logic; -- Noise channel active
signal noi_wav : std_logic_vector(5 downto 0); -- Noise output waveform
begin
en_snd2 <= en_snd and en_snden2;
en_snd4 <= en_snd and en_snden4;
en_snd <= true;
-- Calculate base clock enable (4.194304MHz)
-- process(clk, reset)
-- --to_unsigned(snd_freq * 65536 / clk_freq, 16);
--constant clk_frac : unsigned(15 downto 0) := X"0ABD"; -- clk_freq=100MHz
-- constant clk_frac : unsigned(15 downto 0) := X"1991"; -- clk_freq=42MHz
-- variable divacc : unsigned(15 downto 0);
-- variable acc : unsigned(16 downto 0);
-- begin
-- if reset = '1' then
-- divacc := (others => '0');
-- elsif rising_edge(clk) then
-- Sound base divider clock enable
-- acc := ('0'&divacc) + ('0'&clk_frac);
-- en_snd <= (acc(16) = '1');
-- divacc := acc(15 downto 0);
-- end if;
-- end process;
-- Calculate divided and frame sequencer clock enables
process(clk, en_snd, reset)
variable clkcnt : unsigned(1 downto 0);
variable cnt_512 : unsigned(12 downto 0);
variable temp_512 : unsigned(13 downto 0);
variable framecnt : integer range 0 to 7 := 0;
begin
if reset = '1' then
clkcnt := "00";
cnt_512 := (others => '0');
framecnt := 0;
elsif rising_edge(clk) then
-- Base clock divider
if en_snd then
clkcnt := clkcnt + 1;
if clkcnt(0) = '1' then
en_snden2 <= true;
else
en_snden2 <= false;
end if;
if clkcnt = "11" then
en_snden4 <= true;
else
en_snden4 <= false;
end if;
end if;
-- Frame sequencer (length, envelope, sweep) clock enables
en_len <= false;
en_env <= false;
en_sweep <= false;
if en_512 then
if framecnt = 0 or framecnt = 2 or framecnt = 4 or framecnt = 6 then
en_len <= true;
end if;
if framecnt = 2 or framecnt = 6 then
en_sweep <= true;
end if;
if framecnt = 7 then
en_env <= true;
end if;
if framecnt < 7 then
framecnt := framecnt + 1;
else
framecnt := 0;
end if;
end if;
--
en_512 <= false;
if en_snd then
temp_512 := ('0'&cnt_512) + to_unsigned(1, temp_512'length);
cnt_512 := temp_512(temp_512'high-1 downto temp_512'low);
en_512 <= (temp_512(13) = '1');
end if;
end if;
end process;
-- Registers
registers : process(clk, snd_enable, reset)
variable wav_shift_r : boolean;
variable wav_temp : wav_t;
begin
-- Registers
if snd_enable = '0' then
-- Reset register values
sq1_swper <= (others => '0');
sq1_swdir <= '0';
sq1_swshift <= (others => '0');
sq1_duty <= (others => '0');
sq1_slen <= (others => '0');
sq1_svol <= (others => '0');
sq1_envsgn <= '0';
sq1_envper <= (others => '0');
sq1_freq <= (others => '0');
sq1_lenchk <= '0';
sq1_trigger <= '0';
sq2_duty <= (others => '0');
sq2_slen <= (others => '0');
sq2_svol <= (others => '0');
sq2_envsgn <= '0';
sq2_envper <= (others => '0');
sq2_freq <= (others => '0');
sq2_lenchk <= '0';
sq2_trigger <= '0';
wav_enable <= '0';
wav_volsh <= (others => '0');
wav_freq <= (others => '0');
wav_trigger <= '0';
wav_lenchk <= '0';
wav_shift_r := false;
noi_slen <= (others => '0');
noi_svol <= (others => '0');
noi_envsgn <= '0';
noi_envper <= (others => '0');
noi_freqsh <= (others => '0');
noi_short <= '0';
noi_div <= (others => '0');
noi_trigger <= '0';
noi_lenchk <= '0';
elsif rising_edge(clk) then
if en_snd then
sq1_trigger <= '0';
sq2_trigger <= '0';
wav_trigger <= '0';
noi_trigger <= '0';
end if;
-- Rotate wave table on rising edge of wav_shift
if wav_shift and not wav_shift_r then
wav_temp := wav_ram(0);
for I in 0 to 30 loop
wav_ram(I) <= wav_ram(I+1);
end loop;
wav_ram(31) <= wav_temp;
end if;
if s1_write = '1' then
case s1_addr is
-- Square 1
when "010000" => -- NR10 FF10 -PPP NSSS Sweep period, negate, shift
sq1_swper <= s1_writedata(6 downto 4);
sq1_swdir <= s1_writedata(3);
sq1_swshift <= s1_writedata(2 downto 0);
when "010001" => -- NR11 FF11 DDLL LLLL Duty, Length load (64-L)
sq1_duty <= s1_writedata(7 downto 6);
sq1_slen <= s1_writedata(5 downto 0);
when "010010" => -- NR12 FF12 VVVV APPP Starting volume, Envelope add mode, period
sq1_svol <= s1_writedata(7 downto 4);
sq1_envsgn <= s1_writedata(3);
sq1_envper <= s1_writedata(2 downto 0);
when "010011" => -- NR13 FF13 FFFF FFFF Frequency LSB
sq1_freq(7 downto 0) <= s1_writedata;
when "010100" => -- NR14 FF14 TL-- -FFF Trigger, Length enable, Frequency MSB
sq1_trigger <= s1_writedata(7);
sq1_lenchk <= s1_writedata(6);
sq1_freq(10 downto 8) <= s1_writedata(2 downto 0);
-- Square 2
when "010110" => -- NR21 FF16 DDLL LLLL Duty, Length load (64-L)
sq2_duty <= s1_writedata(7 downto 6);
sq2_slen <= s1_writedata(5 downto 0);
when "010111" => -- NR22 FF17 VVVV APPP Starting volume, Envelope add mode, period
sq2_svol <= s1_writedata(7 downto 4);
sq2_envsgn <= s1_writedata(3);
sq2_envper <= s1_writedata(2 downto 0);
when "011000" => -- NR23 FF18 FFFF FFFF Frequency LSB
sq2_freq(7 downto 0) <= s1_writedata;
when "011001" => -- NR24 FF19 TL-- -FFF Trigger, Length enable, Frequency MSB
sq2_trigger <= s1_writedata(7);
sq2_lenchk <= s1_writedata(6);
sq2_freq(10 downto 8) <= s1_writedata(2 downto 0);
-- Wave
when "011010" => -- NR30 FF1A E--- ---- DAC power
wav_enable <= s1_writedata(7);
when "011011" => -- NR31 FF1B LLLL LLLL Length load (256-L)
wav_slen <= s1_writedata;
when "011100" => -- NR32 FF1C -VV- ---- Volume code (00=0%, 01=100%, 10=50%, 11=25%)
wav_volsh <= s1_writedata(6 downto 5);
when "011101" => -- NR33 FF1D FFFF FFFF Frequency LSB
wav_freq(7 downto 0) <= s1_writedata;
when "011110" => -- NR34 FF1E TL-- -FFF Trigger, Length enable, Frequency MSB
wav_trigger <= s1_writedata(7);
wav_lenchk <= s1_writedata(6);
wav_freq(10 downto 8) <= s1_writedata(2 downto 0);
-- Noise
when "100000" => -- NR41 FF20 --LL LLLL Length load (64-L)
noi_slen <= s1_writedata(5 downto 0);
when "100001" => -- NR42 FF21 VVVV APPP Starting volume, Envelope add mode, period
noi_svol <= s1_writedata(7 downto 4);
noi_envsgn <= s1_writedata(3);
noi_envper <= s1_writedata(2 downto 0);
when "100010" => -- NR43 FF22 SSSS WDDD Clock shift, Width mode of LFSR, Divisor code
noi_freqsh <= s1_writedata(7 downto 4);
noi_short <= s1_writedata(3);
noi_div <= s1_writedata(2 downto 0);
when "100011" => -- NR44 FF23 TL-- ---- Trigger, Length enable
noi_trigger <= s1_writedata(7);
noi_lenchk <= s1_writedata(6);
-- -- Control/Status
-- when "100100" => -- NR50 FF24 ALLL BRRR Vin L enable, Left vol, Vin R enable, Right vol
-- when "100101" => -- NR51 FF25 NW21 NW21 Left enables, Right enables
--
-- Wave Table
when "110000" => -- FF30 0000 1111 Samples 0 and 1
wav_ram(0) <= s1_writedata(7 downto 4);
wav_ram(1) <= s1_writedata(3 downto 0);
when "110001" => -- FF31 0000 1111 Samples 2 and 3
wav_ram(2) <= s1_writedata(7 downto 4);
wav_ram(3) <= s1_writedata(3 downto 0);
when "110010" => -- FF32 0000 1111 Samples 4 and 5
wav_ram(4) <= s1_writedata(7 downto 4);
wav_ram(5) <= s1_writedata(3 downto 0);
when "110011" => -- FF33 0000 1111 Samples 6 and 31
wav_ram(6) <= s1_writedata(7 downto 4);
wav_ram(7) <= s1_writedata(3 downto 0);
when "110100" => -- FF34 0000 1111 Samples 8 and 31
wav_ram(8) <= s1_writedata(7 downto 4);
wav_ram(9) <= s1_writedata(3 downto 0);
when "110101" => -- FF35 0000 1111 Samples 10 and 11
wav_ram(10) <= s1_writedata(7 downto 4);
wav_ram(11) <= s1_writedata(3 downto 0);
when "110110" => -- FF36 0000 1111 Samples 12 and 13
wav_ram(12) <= s1_writedata(7 downto 4);
wav_ram(13) <= s1_writedata(3 downto 0);
when "110111" => -- FF37 0000 1111 Samples 14 and 15
wav_ram(14) <= s1_writedata(7 downto 4);
wav_ram(15) <= s1_writedata(3 downto 0);
when "111000" => -- FF38 0000 1111 Samples 16 and 17
wav_ram(16) <= s1_writedata(7 downto 4);
wav_ram(17) <= s1_writedata(3 downto 0);
when "111001" => -- FF39 0000 1111 Samples 18 and 19
wav_ram(18) <= s1_writedata(7 downto 4);
wav_ram(19) <= s1_writedata(3 downto 0);
when "111010" => -- FF3A 0000 1111 Samples 20 and 21
wav_ram(20) <= s1_writedata(7 downto 4);
wav_ram(21) <= s1_writedata(3 downto 0);
when "111011" => -- FF3B 0000 1111 Samples 22 and 23
wav_ram(22) <= s1_writedata(7 downto 4);
wav_ram(23) <= s1_writedata(3 downto 0);
when "111100" => -- FF3C 0000 1111 Samples 24 and 25
wav_ram(24) <= s1_writedata(7 downto 4);
wav_ram(25) <= s1_writedata(3 downto 0);
when "111101" => -- FF3D 0000 1111 Samples 26 and 27
wav_ram(26) <= s1_writedata(7 downto 4);
wav_ram(27) <= s1_writedata(3 downto 0);
when "111110" => -- FF3E 0000 1111 Samples 28 and 29
wav_ram(28) <= s1_writedata(7 downto 4);
wav_ram(29) <= s1_writedata(3 downto 0);
when "111111" => -- FF3F 0000 1111 Samples 30 and 31
wav_ram(30) <= s1_writedata(7 downto 4);
wav_ram(31) <= s1_writedata(3 downto 0);
when others =>
null;
end case;
end if;
if s1_read = '1' then
case s1_addr is
-- Square 1
when "010000" => -- NR10 FF10 -PPP NSSS Sweep period, negate, shift
s1_readdata <= '1' & sq1_swper & sq1_swdir & sq1_swshift;
when "010001" => -- NR11 FF11 DDLL LLLL Duty, Length load (64-L)
s1_readdata <= sq1_duty & "111111";
when "010010" => -- NR12 FF12 VVVV APPP Starting volume, Envelope add mode, period
s1_readdata <= sq1_vol & sq1_envsgn & sq1_envper;
when "010011" => -- NR13 FF13 FFFF FFFF Frequency LSB
s1_readdata <= X"FF";
when "010100" => -- NR14 FF14 TL-- -FFF Trigger, Length enable, Frequency MSB
s1_readdata <= '0' & sq1_lenchk & "111111";
-- Square 2
when "010110" => -- NR21 FF16 DDLL LLLL Duty, Length load (64-L)
s1_readdata <= sq2_duty & "111111";
when "010111" => -- NR22 FF17 VVVV APPP Starting volume, Envelope add mode, period
s1_readdata <= sq2_vol & sq2_envsgn & sq2_envper;
when "011000" => -- NR23 FF18 FFFF FFFF Frequency LSB
s1_readdata <= X"FF";
when "011001" => -- NR24 FF19 TL-- -FFF Trigger, Length enable, Frequency MSB
s1_readdata <= '0' & sq2_lenchk & "111111";
when "100110" => -- NR52 FF26 P--- NW21 Power control/status, Channel length statuses
s1_readdata <= snd_enable & "00000" & sq2_playing & sq1_playing;
-- Wave
when "011010" => -- NR30 FF1A E--- ---- DAC power
s1_readdata <= wav_enable & "1111111";
when "011011" => -- NR31 FF1B LLLL LLLL Length load (256-L)
s1_readdata <= X"FF";
when "011100" => -- NR32 FF1C -VV- ---- Volume code (00=0%, 01=100%, 10=50%, 11=25%)
s1_readdata <= '1' & wav_volsh & "11111";
when "011101" => -- NR33 FF1D FFFF FFFF Frequency LSB
s1_readdata <= X"FF";
when "011110" => -- NR34 FF1E TL-- -FFF Trigger, Length enable, Frequency MSB
s1_readdata <= wav_trigger & wav_lenchk & "111111";
-- Noise
when "100000" => -- NR41 FF20 --LL LLLL Length load (64-L)
s1_readdata <= X"FF";
when "100001" => -- NR42 FF21 VVVV APPP Starting volume, Envelope add mode, period
s1_readdata <= noi_svol & noi_envsgn & noi_envper;
when "100010" => -- NR43 FF22 SSSS WDDD Clock shift, Width mode of LFSR, Divisor code
s1_readdata <= noi_freqsh & noi_short & noi_div;
when "100011" => -- NR44 FF23 TL-- ---- Trigger, Length enable
s1_readdata <= noi_trigger & noi_lenchk & "111111";
-- Wave Table
when "110000" => -- FF30 0000 1111 Samples 0 and 1
s1_readdata <= wav_ram(0) & wav_ram(1);
when "110001" => -- FF31 0000 1111 Samples 2 and 3
s1_readdata <= wav_ram(2) & wav_ram(3);
when "110010" => -- FF32 0000 1111 Samples 4 and 5
s1_readdata <= wav_ram(4) & wav_ram(5);
when "110011" => -- FF33 0000 1111 Samples 6 and 31
s1_readdata <= wav_ram(6) & wav_ram(7);
when "110100" => -- FF34 0000 1111 Samples 8 and 31
s1_readdata <= wav_ram(8) & wav_ram(9);
when "110101" => -- FF35 0000 1111 Samples 10 and 11
s1_readdata <= wav_ram(10) & wav_ram(11);
when "110110" => -- FF36 0000 1111 Samples 12 and 13
s1_readdata <= wav_ram(12) & wav_ram(13);
when "110111" => -- FF37 0000 1111 Samples 14 and 15
s1_readdata <= wav_ram(14) & wav_ram(15);
when "111000" => -- FF38 0000 1111 Samples 16 and 17
s1_readdata <= wav_ram(16) & wav_ram(17);
when "111001" => -- FF39 0000 1111 Samples 18 and 19
s1_readdata <= wav_ram(18) & wav_ram(19);
when "111010" => -- FF3A 0000 1111 Samples 20 and 21
s1_readdata <= wav_ram(20) & wav_ram(21);
when "111011" => -- FF3B 0000 1111 Samples 22 and 23
s1_readdata <= wav_ram(22) & wav_ram(23);
when "111100" => -- FF3C 0000 1111 Samples 24 and 25
s1_readdata <= wav_ram(24) & wav_ram(25);
when "111101" => -- FF3D 0000 1111 Samples 26 and 27
s1_readdata <= wav_ram(26) & wav_ram(27);
when "111110" => -- FF3E 0000 1111 Samples 28 and 29
s1_readdata <= wav_ram(28) & wav_ram(29);
when "111111" => -- FF3F 0000 1111 Samples 30 and 31
s1_readdata <= wav_ram(30) & wav_ram(31);
when others =>
s1_readdata <= X"FF";
end case;
end if;
wav_shift_r := wav_shift;
end if;
if reset = '1' then
snd_enable <= '0';
elsif rising_edge(clk) then
if s1_write = '1' and s1_addr = "100110" then
-- NR52 FF26 P--- NW21 Power control/status, Channel length statuses
snd_enable <= s1_writedata(7);
end if;
end if;
end process;
sound : process(clk, snd_enable, en_snd, en_len, en_env, en_sweep)
constant duty_0 : std_logic_vector(0 to 7) := "00000001";
constant duty_1 : std_logic_vector(0 to 7) := "10000001";
constant duty_2 : std_logic_vector(0 to 7) := "10000111";
constant duty_3 : std_logic_vector(0 to 7) := "01111110";
variable sq1_fcnt : unsigned(10 downto 0);
variable sq1_phase : integer range 0 to 7;
variable sq1_len : std_logic_vector(6 downto 0);
variable sq1_envcnt : std_logic_vector(2 downto 0); -- Sq1 envelope timer count
variable sq1_swcnt : std_logic_vector(2 downto 0); -- Sq1 sweep timer count
variable sq1_swoffs : unsigned(11 downto 0);
variable sq1_swfr : unsigned(11 downto 0);
variable sq1_out : std_logic;
variable sq2_fcnt : unsigned(10 downto 0);
variable sq2_phase : integer range 0 to 7;
variable sq2_len : std_logic_vector(6 downto 0);
variable sq2_envcnt : std_logic_vector(2 downto 0); -- Sq2 envelope timer count
variable sq2_out : std_logic;
variable wav_fcnt : unsigned(10 downto 0);
variable wav_len : std_logic_vector(8 downto 0);
variable noi_divisor: unsigned(10 downto 0); -- Noise frequency divisor
variable noi_freq : unsigned(10 downto 0); -- Noise frequency (calculated)
variable noi_fcnt : unsigned(10 downto 0);
variable noi_lfsr : unsigned(15 downto 0);
variable noi_len : std_logic_vector(6 downto 0);
variable noi_envcnt : std_logic_vector(2 downto 0); -- Noise envelope timer count
variable noi_out : std_logic;
variable acc_fcnt : unsigned(11 downto 0);
begin
-- Sound processing
if snd_enable = '0' then
sq1_playing <= '0';
sq1_fr2 <= (others => '0');
sq1_fcnt := (others => '0');
sq1_phase := 0;
sq1_len := (others => '0');
sq1_vol <= "0000";
sq1_envcnt := "000";
sq1_swcnt := "000";
sq1_swoffs := (others => '0');
sq1_swfr := (others => '0');
sq1_out := '0';
sq2_playing <= '0';
sq2_fr2 <= (others => '0');
sq2_fcnt := (others => '0');
sq2_phase := 0;
sq2_len := (others => '0');
sq2_vol <= "0000";
sq2_envcnt := "000";
sq2_out := '0';
wav_fcnt := (others => '0');
wav_len := (others => '0');
noi_playing <= '0';
noi_fr2 <= (others => '0');
noi_fcnt := (others => '0');
noi_lfsr := (others => '1');
noi_len := (others => '0');
noi_vol <= "0000";
noi_envcnt := "000";
noi_out := '0';
elsif rising_edge(clk) then
if en_snd4 then
-- Sq1 frequency timer
if sq1_playing = '1' then
acc_fcnt := ('0'&sq1_fcnt) + to_unsigned(1, acc_fcnt'length);
if acc_fcnt(acc_fcnt'high) = '1' then
if sq1_phase < 7 then
sq1_phase := sq1_phase + 1;
else
sq1_phase := 0;
end if;
sq1_fcnt := unsigned(sq1_fr2);
else
sq1_fcnt := acc_fcnt(sq1_fcnt'range);
end if;
end if;
-- Sq2 frequency timer
if sq2_playing = '1' then
acc_fcnt := ('0'&sq2_fcnt) + to_unsigned(1, acc_fcnt'length);
if acc_fcnt(acc_fcnt'high) = '1' then
if sq2_phase < 7 then
sq2_phase := sq2_phase + 1;
else
sq2_phase := 0;
end if;
sq2_fcnt := unsigned(sq2_fr2);
else
sq2_fcnt := acc_fcnt(sq2_fcnt'range);
end if;
end if;
-- Noi frequency timer
if noi_playing = '1' then
acc_fcnt := ('0'&noi_fcnt) + to_unsigned(1, acc_fcnt'length);
if acc_fcnt(acc_fcnt'high) = '1' then
-- Noise LFSR
if noi_short = '1' then
noi_lfsr := (noi_lfsr(0) xor noi_lfsr(1)) & noi_lfsr(15 downto 8) & (noi_lfsr(0) xor noi_lfsr(1)) & noi_lfsr(6 downto 1);
else
noi_lfsr := (noi_lfsr(0) xor noi_lfsr(1)) & noi_lfsr(15 downto 1);
end if;
noi_out := not noi_lfsr(0);
noi_fcnt := unsigned(noi_fr2);
else
noi_fcnt := acc_fcnt(noi_fcnt'range);
end if;
end if;
case sq1_duty is
when "00" => sq1_out := duty_0(sq1_phase);
when "01" => sq1_out := duty_1(sq1_phase);
when "10" => sq1_out := duty_2(sq1_phase);
when "11" => sq1_out := duty_3(sq1_phase);
when others => null;
end case;
if sq1_out = '1' then
sq1_wav <= sq1_vol & "00";
else
sq1_wav <= "000000";
end if;
case sq2_duty is
when "00" => sq2_out := duty_0(sq2_phase);
when "01" => sq2_out := duty_1(sq2_phase);
when "10" => sq2_out := duty_2(sq2_phase);
when "11" => sq2_out := duty_3(sq2_phase);
when others => null;
end case;
if sq2_out = '1' then
sq2_wav <= sq2_vol & "00";
else
sq2_wav <= "000000";
end if;
if noi_out = '1' then
noi_wav <= noi_vol & "00";
else
noi_wav <= "000000";
end if;
end if;
-- Square channel 1
if sq1_playing = '1' then
-- Length counter
if en_len then
if sq1_len(6) = '0' then
sq1_len := std_logic_vector(unsigned(sq1_len) + to_unsigned(1, sq1_len'length));
end if;
end if;
-- Envelope counter
if en_env then
if sq1_envper /= "000" then
sq1_envcnt := std_logic_vector(unsigned(sq1_envcnt) + to_unsigned(1, sq1_envcnt'length));
if sq1_envcnt = sq1_envper then
if sq1_envsgn = '1' then
if sq1_vol /= "1111" then
sq1_vol <= std_logic_vector(unsigned(sq1_vol) + to_unsigned(1, sq1_vol'length));
end if;
else
if sq1_vol /= "0000" then
sq1_vol <= std_logic_vector(unsigned(sq1_vol) - to_unsigned(1, sq1_vol'length));
end if;
end if;
sq1_envcnt := "000";
end if;
end if;
end if;
-- Sweep processing
if en_sweep or sq1_trigger = '1' then
case sq1_swshift is
when "000" => sq1_swoffs := unsigned('0' & sq1_fr2);
when "001" => sq1_swoffs := "00" & unsigned(sq1_fr2(10 downto 1));
when "010" => sq1_swoffs := "000" & unsigned(sq1_fr2(10 downto 2));
when "011" => sq1_swoffs := "0000" & unsigned(sq1_fr2(10 downto 3));
when "100" => sq1_swoffs := "00000" & unsigned(sq1_fr2(10 downto 4));
when "101" => sq1_swoffs := "000000" & unsigned(sq1_fr2(10 downto 5));
when "110" => sq1_swoffs := "0000000" & unsigned(sq1_fr2(10 downto 6));
when "111" => sq1_swoffs := "00000000" & unsigned(sq1_fr2(10 downto 7));
when others => sq1_swoffs := unsigned('0' & sq1_fr2);
end case;
-- Calculate next sweep frequency
if sq1_swper /= "000" then
if sq1_swdir = '0' then
sq1_swfr := ('0' & unsigned(sq1_fr2)) - sq1_swoffs;
else
sq1_swfr := ('0' & unsigned(sq1_fr2)) + sq1_swoffs;
end if;
else -- Sweep disabled
sq1_swfr := unsigned('0' & sq1_fr2);
end if;
-- Sweep counter
if sq1_swper /= "000" then
sq1_swcnt := std_logic_vector(unsigned(sq1_swcnt) + to_unsigned(1, sq1_swcnt'length));
if sq1_swcnt = sq1_swper then
sq1_fr2 <= std_logic_vector(sq1_swfr(10 downto 0));
sq1_swcnt := "000";
end if;
end if;
end if;
-- Check for end of playing conditions
if sq1_vol = X"0" -- Volume == 0
or (sq1_lenchk = '1' and sq1_len(6) = '1') -- Play length timer overrun
or (sq1_swper /= "000" and sq1_swfr(11) = '1') -- Sweep frequency overrun
then
sq1_playing <= '0';
sq1_envcnt := "000";
sq1_swcnt := "000";
--sq1_wav <= "000000";
end if;
end if;
-- Check sample trigger and start playing
if sq1_trigger = '1' then
sq1_fr2 <= sq1_freq;
sq1_fcnt := unsigned(sq1_freq);
noi_lfsr := (others => '1');
sq1_playing <= '1';
sq1_vol <= sq1_svol;
sq1_envcnt := "000";
sq1_swcnt := "000";
sq1_len := '0' & sq1_slen;
sq1_phase := 0;
end if;
-- Square channel 2
if sq2_playing = '1' then
-- Length counter
if en_len then
if sq2_len(6) = '0' then
sq2_len := std_logic_vector(unsigned(sq2_len) + to_unsigned(1, sq2_len'length));
end if;
end if;
-- Envelope counter
if en_env then
if sq2_envper /= "000" then
sq2_envcnt := std_logic_vector(unsigned(sq2_envcnt) + to_unsigned(1, sq2_envcnt'length));
if sq2_envcnt = sq2_envper then
if sq2_envsgn = '1' then
if sq2_vol /= "1111" then
sq2_vol <= std_logic_vector(unsigned(sq2_vol) + to_unsigned(1, sq2_vol'length));
end if;
else
if sq2_vol /= "0000" then
sq2_vol <= std_logic_vector(unsigned(sq2_vol) - to_unsigned(1, sq2_vol'length));
end if;
end if;
sq2_envcnt := "000";
end if;
end if;
end if;
-- Check for end of playing conditions
if sq2_vol = X"0" -- Volume == 0
or (sq2_lenchk = '1' and sq2_len(6) = '1') -- Play length timer overrun
then
sq2_playing <= '0';
sq2_envcnt := "000";
--sq2_wav <= "000000";
end if;
end if;
-- Check sample trigger and start playing
if sq2_trigger = '1' then
sq2_fr2 <= sq2_freq;
sq2_fcnt := unsigned(sq2_freq);
sq2_playing <= '1';
sq2_vol <= sq2_svol;
sq2_envcnt := "000";
sq2_len := '0' & sq2_slen;
sq2_phase := 0;
end if;
-- Noise channel
if noi_playing = '1' then
-- Length counter
if en_len then
if noi_len(6) = '0' then
noi_len := std_logic_vector(unsigned(noi_len) + to_unsigned(1, noi_len'length));
end if;
end if;
-- Envelope counter
if en_env then
if noi_envper /= "000" then
noi_envcnt := std_logic_vector(unsigned(noi_envcnt) + to_unsigned(1, noi_envcnt'length));
if noi_envcnt = noi_envper then
if noi_envsgn = '1' then
if noi_vol /= "1111" then
noi_vol <= std_logic_vector(unsigned(noi_vol) + to_unsigned(1, noi_vol'length));
end if;
else
if noi_vol /= "0000" then
noi_vol <= std_logic_vector(unsigned(noi_vol) - to_unsigned(1, noi_vol'length));
end if;
end if;
noi_envcnt := "000";
end if;
end if;
end if;
-- Check for end of playing conditions
if noi_vol = X"0" -- Volume == 0
or (noi_lenchk = '1' and noi_len(6) = '1') -- Play length timer overrun
then
noi_playing <= '0';
noi_envcnt := "000";
--sq2_wav <= "000000";
end if;
end if;
-- Check sample trigger and start playing
if noi_trigger = '1' then
-- Calculate noise frequency
case noi_div is
when "000" => noi_divisor := to_unsigned(2048 - 8, noi_divisor'length);
when "001" => noi_divisor := to_unsigned(2048 - 16, noi_divisor'length);
when "010" => noi_divisor := to_unsigned(2048 - 32, noi_divisor'length);
when "011" => noi_divisor := to_unsigned(2048 - 48, noi_divisor'length);
when "100" => noi_divisor := to_unsigned(2048 - 64, noi_divisor'length);
when "101" => noi_divisor := to_unsigned(2048 - 80, noi_divisor'length);
when "110" => noi_divisor := to_unsigned(2048 - 96, noi_divisor'length);
when others => noi_divisor := to_unsigned(2048 - 112, noi_divisor'length);
end case;
-- case noi_freqsh is
-- when "000" => noi_freq := unsigned(noi_divisor);
-- when "001" => noi_freq := '0' & unsigned(noi_divisor(10 downto 1));
-- when "010" => noi_freq := "00" & unsigned(noi_divisor(10 downto 2));
-- when "011" => noi_freq := "000" & unsigned(noi_divisor(10 downto 3));
-- when "100" => noi_freq := "0000" & unsigned(noi_divisor(10 downto 4));
-- when "101" => noi_freq := "00000" & unsigned(noi_divisor(10 downto 5));
-- when "110" => noi_freq := "000000" & unsigned(noi_divisor(10 downto 6));
-- when "111" => noi_freq := "0000000" & unsigned(noi_divisor(10 downto 7));
-- when others => noi_freq := unsigned(noi_divisor);
-- end case;
noi_freq := noi_divisor sll to_integer(unsigned(noi_freqsh));
noi_fr2 <= std_logic_vector(noi_freq);
noi_fcnt := noi_freq;
noi_playing <= '1';
noi_vol <= noi_svol;
noi_envcnt := "000";
noi_len := '0' & noi_slen;
end if;
if en_snd2 then
-- Wave frequency timer
wav_shift <= false;
if wav_playing = '1' then
acc_fcnt := ('0'&wav_fcnt) + to_unsigned(1, acc_fcnt'length);
if acc_fcnt(acc_fcnt'high) = '1' then
wav_shift <= true;
wav_fcnt := unsigned(wav_fr2);
else
wav_fcnt := acc_fcnt(wav_fcnt'range);
end if;
end if;
end if;
-- Wave channel
if wav_playing = '1' then
-- Length counter
if en_len then
if wav_len(8) = '0' then
wav_len := std_logic_vector(unsigned(wav_len) + to_unsigned(1, wav_len'length));
end if;
end if;
-- Check for end of playing conditions
if (wav_lenchk = '1' and wav_len(8) = '1') then
wav_playing <= '0';
wav_wav <= "000000";
end if;
end if;
-- Check sample trigger and start playing
if wav_trigger = '1' then
wav_fr2 <= wav_freq;
wav_fcnt := unsigned(wav_freq);
wav_playing <= '1';
wav_len := '0' & wav_slen;
end if;
if wav_enable = '1' and wav_volsh /= "00" then
case wav_volsh is
when "01" => wav_wav <= wav_ram(0) & "00";
when "10" => wav_wav <= '0' & wav_ram(0) & '0';
when "11" => wav_wav <= "00" & wav_ram(0);
when others => wav_wav <= (others => 'X');
end case;
else
wav_wav <= "000000";
end if;
end if; -- snd_enable
end process sound;
-- Test
process(clk, en_512, reset)
variable l : std_logic_vector(15 downto 0);
begin
if reset = '1' then
l := x"4000";
elsif rising_edge(clk) then
if en_512 then
l := not l;
end if;
-- snd_left <= l;
end if;
end process;
-- Mixer
mixer : process(sq1_wav, sq2_wav, noi_wav, wav_wav)
variable snd_left_in : unsigned(7 downto 0);
variable snd_right_in : unsigned(7 downto 0);
begin
snd_left_in := (others => '0');
snd_right_in := (others => '0');
snd_left_in := snd_left_in + ("00"&unsigned(sq1_wav));
snd_left_in := snd_left_in + ("00"&unsigned(wav_wav));
snd_right_in := snd_right_in + ("00"&unsigned(sq2_wav));
snd_right_in := snd_right_in + ("00"&unsigned(noi_wav));
snd_left <= std_logic_vector(snd_left_in) & X"00";
snd_right <= std_logic_vector(snd_right_in) & X"00";
end process;
end SYN;

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,172 @@
// megafunction wizard: %RAM: 1-PORT%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altsyncram
// ============================================================
// File Name: iram.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 iram (
address,
clock,
data,
wren,
q);
input [12:0] address;
input clock;
input [7:0] data;
input wren;
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),
.data_a (data),
.wren_a (wren),
.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_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 = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 8192,
altsyncram_component.operation_mode = "SINGLE_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
altsyncram_component.widthad_a = 13,
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 "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: Clken NUMERIC "0"
// 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 "8192"
// 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 "0"
// 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 "13"
// 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 "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
// 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 "8192"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
// 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 "13"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL "address[12..0]"
// 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 13 0 address 0 0 13 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 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 iram.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL iram.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL iram.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL iram.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL iram_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL iram_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,79 @@
module keyboard
(
input clk,
input reset,
input ps2_kbd_clk,
input ps2_kbd_data,
output reg[7:0] joystick
);
reg [11:0] shift_reg = 12'hFFF;
wire[11:0] kdata = {ps2_kbd_data,shift_reg[11:1]};
wire [7:0] kcode = kdata[9:2];
reg release_btn = 0;
reg [7:0] code;
reg input_strobe = 0;
always @(negedge clk) begin
reg old_reset = 0;
old_reset <= reset;
if(~old_reset & reset)begin
joystick <= 0;
end
if(input_strobe) begin
case(code)
'h75: joystick[3] <= ~release_btn; // arrow up
'h72: joystick[2] <= ~release_btn; // arrow down
'h6B: joystick[1] <= ~release_btn; // arrow left
'h74: joystick[0] <= ~release_btn; // arrow right
'h29: joystick[4] <= ~release_btn; // Space
'h11: joystick[5] <= ~release_btn; // Left Alt
'h0D: joystick[6] <= ~release_btn; // Tab
'h76: joystick[7] <= ~release_btn; // Escape
endcase
end
end
always @(posedge clk) begin
reg [3:0] prev_clk = 0;
reg old_reset = 0;
reg action = 0;
old_reset <= reset;
input_strobe <= 0;
if(~old_reset & reset)begin
prev_clk <= 0;
shift_reg <= 12'hFFF;
end else begin
prev_clk <= {ps2_kbd_clk,prev_clk[3:1]};
if(prev_clk == 1) begin
if (kdata[11] & ^kdata[10:2] & ~kdata[1] & kdata[0]) begin
shift_reg <= 12'hFFF;
if (kcode == 8'he0) ;
// Extended key code follows
else if (kcode == 8'hf0)
// Release code follows
action <= 1;
else begin
// Cancel extended/release flags for next time
action <= 0;
release_btn <= action;
code <= kcode;
input_strobe <= 1;
end
end else begin
shift_reg <= kdata;
end
end
end
end
endmodule

View File

@@ -0,0 +1,147 @@
// Gameboy for the MiST
// (c) 2015 Till Harbaum
// The gameboy lcd runs from a shift register which is filled at 4194304 pixels/sec
module lcd (
input clk,
input clkena,
input [1:0] data,
input [1:0] mode,
input tint,
input inv,
// pixel clock
input pclk,
input on,
// VGA output
output reg hs,
output reg vs,
output [5:0] r,
output [5:0] g,
output [5:0] b
);
// Mode 00: h-blank
// Mode 01: v-blank
// Mode 10: oam
// Mode 11: oam and vram
// space for 2*160 pixel
reg [7:0] shift_reg_wptr;
reg p_toggle;
reg [1:0] shift_reg [511:0];
reg [1:0] last_mode_in;
// shift register input
always @(posedge clk) begin
last_mode_in <= mode;
// end of vsync
if(clkena) begin
shift_reg[{p_toggle, shift_reg_wptr}] <= data;
shift_reg_wptr <= shift_reg_wptr + 8'd1;
end
// reset write pointer at end of hsync phase
if((mode != 2'b00) && (last_mode_in == 2'b00)) begin
shift_reg_wptr <= 8'd0;
p_toggle <= !p_toggle;
end
end
//
parameter H = 160; // width of visible area
parameter HFP = 24; // unused time before hsync
parameter HS = 20; // width of hsync
parameter HBP = 24; // unused time after hsync
// total = 228
parameter V = 576; // height of visible area
parameter VFP = 2; // unused time before vsync
parameter VS = 2; // width of vsync
parameter VBP = 36; // unused time after vsync
// total = 616
reg[7:0] h_cnt; // horizontal pixel counter
reg[9:0] v_cnt; // vertical pixel counter
// horizontal pixel counter
reg [1:0] last_mode_h;
always@(posedge pclk) begin
last_mode_h <= mode;
if(h_cnt==H+HFP+HS+HBP-1) h_cnt <= 0;
else h_cnt <= h_cnt + 1;
// generate negative hsync signal
if(h_cnt == H+HFP) hs <= 1'b0;
if(h_cnt == H+HFP+HS) hs <= 1'b1;
// synchronize to input mode
// end of hblank
if((mode == 2'b10) && (last_mode_h == 2'b00))
h_cnt <= 0;
end
// veritical pixel counter
reg [1:0] last_mode_v;
always@(posedge pclk) begin
// the vertical counter is processed at the begin of each hsync
if(h_cnt == H+HFP+HS+HBP-1) begin
if(v_cnt==VS+VFP+V+VBP-1) v_cnt <= 0;
else v_cnt <= v_cnt + 1;
// generate positive vsync signal
if(v_cnt == V+VFP) vs <= 1'b1;
if(v_cnt == V+VFP+VS) vs <= 1'b0;
last_mode_v <= mode;
// synchronize to input mode
// end of mode 01 (vblank)
// make and offset of - 4 for the 4 line delay of the scandoubler
if((mode != 2'b01) && (last_mode_v == 2'b01))
v_cnt <= 616-4;
end
end
// -------------------------------------------------------------------------------
// ------------------------------- pixel generator -------------------------------
// -------------------------------------------------------------------------------
reg blank;
reg [1:0] pixel_reg;
reg [7:0] shift_reg_rptr;
always@(posedge pclk) begin
// visible area?
if((v_cnt < V) && (h_cnt < H)) begin
blank <= 1'b0;
pixel_reg <= shift_reg[{!p_toggle, shift_reg_rptr}];
shift_reg_rptr <= shift_reg_rptr + 8'd1;
end else begin
blank <= 1'b1;
shift_reg_rptr <= 8'd0;
end
end
//wire [1:0] pixel = on?pixel_reg:2'b00;
wire [1:0] pixel = on? (pixel_reg ^ {inv,inv}) :2'b00;
// gameboy "color" palette
wire [5:0] yellow_r = (pixel==0)?6'b100111:(pixel==1)?6'b100000: // 1:100011
(pixel==2)?6'b001100:6'b000111;
wire [5:0] yellow_g = (pixel==0)?6'b101111:(pixel==1)?6'b101000: // 1:101011
(pixel==2)?6'b011001:6'b000100;
wire [5:0] yellow_b = (pixel==0)?6'b000100:(pixel==1)?6'b000010: // 1:000100
(pixel==2)?6'b001100:6'b000100;
// greyscale
wire [5:0] grey = (pixel==0)?6'd63:(pixel==1)?6'd42:(pixel==2)?6'd24:6'd0;
assign r = blank?6'b000000:tint?yellow_r:grey;
assign g = blank?6'b000000:tint?yellow_g:grey;
assign b = blank?6'b000000:tint?yellow_b:grey;
endmodule

View File

@@ -0,0 +1,491 @@
//
// 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,
input ps2_caps_led,
// ARM -> FPGA download
output reg ioctl_download = 0, // signal indicating an active download
output reg [7:0] ioctl_index, // menu index used to upload the file
output ioctl_wr,
output reg [23: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 [9: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;
wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1};
// 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];
// reading keyboard LED status
8'h1f:
spi_do <= kbd_led[~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 [23: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 [23: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
addr <= 0;
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
assign ioctl_wr = |ioctl_wrd;
reg [1:0] ioctl_wrd;
always@(negedge clk_sys) begin
reg rclkD, rclkD2;
rclkD <= rclk;
rclkD2 <= rclkD;
ioctl_wrd<= {ioctl_wrd[0],1'b0};
if(rclkD & ~rclkD2) begin
ioctl_dout <= data_w;
ioctl_addr <= addr_w;
ioctl_wrd <= 2'b11;
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

View File

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

View File

@@ -0,0 +1,421 @@
// 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.0 Build 162 10/23/2013 SJ Web Edition
// ************************************************************
//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.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll (
inclk0,
c0,
c1,
c2,
c3,
c4,
locked);
input inclk0;
output c0;
output c1;
output c2;
output c3;
output c4;
output locked;
wire [4:0] sub_wire0;
wire sub_wire3;
wire [0:0] sub_wire9 = 1'h0;
wire [4:4] sub_wire6 = sub_wire0[4:4];
wire [2:2] sub_wire5 = sub_wire0[2:2];
wire [0:0] sub_wire4 = sub_wire0[0:0];
wire [3:3] sub_wire2 = sub_wire0[3:3];
wire [1:1] sub_wire1 = sub_wire0[1:1];
wire c1 = sub_wire1;
wire c3 = sub_wire2;
wire locked = sub_wire3;
wire c0 = sub_wire4;
wire c2 = sub_wire5;
wire c4 = sub_wire6;
wire sub_wire7 = inclk0;
wire [1:0] sub_wire8 = {sub_wire9, sub_wire7};
altpll altpll_component (
.inclk (sub_wire8),
.clk (sub_wire0),
.locked (sub_wire3),
.activeclock (),
.areset (1'b0),
.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 = 62,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 77,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 62,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 77,
altpll_component.clk1_phase_shift = "-2500",
altpll_component.clk2_divide_by = 130,
altpll_component.clk2_duty_cycle = 50,
altpll_component.clk2_multiply_by = 77,
altpll_component.clk2_phase_shift = "0",
altpll_component.clk3_divide_by = 260,
altpll_component.clk3_duty_cycle = 50,
altpll_component.clk3_multiply_by = 77,
altpll_component.clk3_phase_shift = "0",
altpll_component.clk4_divide_by = 520,
altpll_component.clk4_duty_cycle = 50,
altpll_component.clk4_multiply_by = 77,
altpll_component.clk4_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_UNUSED",
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_USED",
altpll_component.port_clk4 = "PORT_USED",
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 "62"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "62"
// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "130"
// Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "260"
// Retrieval info: PRIVATE: DIV_FACTOR4 NUMERIC "520"
// 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: DUTY_CYCLE3 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE4 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "33.532257"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "33.532257"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "15.992308"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "7.996154"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE4 STRING "3.998077"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT3 STRING "ps"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT4 STRING "ps"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK3 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK4 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "77"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "77"
// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "77"
// Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "77"
// Retrieval info: PRIVATE: MULT_FACTOR4 NUMERIC "77"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "33.55714300"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "33.55714300"
// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "16.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "8.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ4 STRING "4.00000000"
// 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_MODE3 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE4 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: OUTPUT_FREQ_UNIT3 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT4 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 "-2500.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT4 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 "ps"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 STRING "ps"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT4 STRING "ps"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
// 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: STICKY_CLK3 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK4 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_CLK3 STRING "1"
// Retrieval info: PRIVATE: USE_CLK4 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_CLKENA3 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA4 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 "62"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "77"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "62"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "77"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "-2500"
// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "130"
// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "77"
// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "260"
// Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "77"
// Retrieval info: CONSTANT: CLK3_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK4_DIVIDE_BY NUMERIC "520"
// Retrieval info: CONSTANT: CLK4_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK4_MULTIPLY_BY NUMERIC "77"
// Retrieval info: CONSTANT: CLK4_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_UNUSED"
// 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_USED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_USED"
// 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: 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: c3 0 0 0 0 OUTPUT_CLK_EXT VCC "c3"
// Retrieval info: USED_PORT: c4 0 0 0 0 OUTPUT_CLK_EXT VCC "c4"
// 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: @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: c3 0 0 0 0 @clk 0 0 1 3
// Retrieval info: CONNECT: c4 0 0 0 0 @clk 0 0 1 4
// 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,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
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
`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 )
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,150 @@
//
// sdram.v
//
// sdram controller implementation for the MiST board
// https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module sdram (
// interface to the MT48LC16M16 chip
inout [15:0] sd_data, // 16 bit bidirectional data bus
output reg [12:0] sd_addr, // 13 bit multiplexed address bus
output reg [1:0] sd_dqm, // two byte masks
output reg[1:0] sd_ba, // two banks
output sd_cs, // a single chip select
output sd_we, // write enable
output sd_ras, // row address select
output sd_cas, // columns address select
// cpu/chipset interface
input init, // init signal after FPGA config to initialize RAM
input clk, // sdram is accessed at up to 128MHz
input clkref, // reference clock to sync to
input [15:0] din, // data input from chipset/cpu
output [15:0] dout, // data output to chipset/cpu
input [23:0] addr, // 24 bit word address
input [1:0] ds, // data strobe for hi/low byte
input oe, // cpu/chipset requests read
input we // cpu/chipset requests write
);
// no burst configured
localparam RASCAS_DELAY = 3'd3; // tRCD>=20ns -> 2 cycles@64MHz
localparam BURST_LENGTH = 3'b000; // 000=none, 001=2, 010=4, 011=8
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
localparam CAS_LATENCY = 3'd3; // 2/3 allowed
localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
// ---------------------------------------------------------------------
// ------------------------ cycle state machine ------------------------
// ---------------------------------------------------------------------
localparam STATE_IDLE = 3'd0; // first state in cycle
localparam STATE_CMD_START = 3'd1; // state in which a new command can be started
localparam STATE_CMD_CONT = STATE_CMD_START + RASCAS_DELAY - 3'd1; // 4 command can be continued
localparam STATE_LAST = 3'd7; // last state in cycle
reg [2:0] q;
always @(posedge clk) begin
// 32Mhz counter synchronous to 4 Mhz clock
// force counter to pass state 5->6 exactly after the rising edge of clkref
// since clkref is two clocks early
if(((q == 7) && ( clkref == 0)) ||
((q == 0) && ( clkref == 1)) ||
((q != 7) && (q != 0)))
q <= q + 3'd1;
end
// ---------------------------------------------------------------------
// --------------------------- startup/reset ---------------------------
// ---------------------------------------------------------------------
// wait 1ms (32 clkref cycles) after FPGA config is done before going
// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0)
reg [4:0] reset;
always @(posedge clk) begin
if(init) reset <= 5'h1f;
else if((q == STATE_LAST) && (reset != 0))
reset <= reset - 5'd1;
end
// ---------------------------------------------------------------------
// ------------------ generate ram control signals ---------------------
// ---------------------------------------------------------------------
// all possible commands
localparam CMD_INHIBIT = 4'b1111;
localparam CMD_NOP = 4'b0111;
localparam CMD_ACTIVE = 4'b0011;
localparam CMD_READ = 4'b0101;
localparam CMD_WRITE = 4'b0100;
localparam CMD_BURST_TERMINATE = 4'b0110;
localparam CMD_PRECHARGE = 4'b0010;
localparam CMD_AUTO_REFRESH = 4'b0001;
localparam CMD_LOAD_MODE = 4'b0000;
reg [3:0] sd_cmd; // current command sent to sd ram
// drive control signals according to current command
assign sd_cs = sd_cmd[3];
assign sd_ras = sd_cmd[2];
assign sd_cas = sd_cmd[1];
assign sd_we = sd_cmd[0];
assign sd_data = we?din:16'bZZZZZZZZZZZZZZZZ;
assign dout = sd_data;
always @(posedge clk) begin
sd_cmd <= CMD_INHIBIT;
if(reset != 0) begin
sd_ba <= 2'b00;
sd_dqm <= 2'b00;
if(reset == 13) sd_addr <= 13'b0010000000000;
else sd_addr <= MODE;
if(q == STATE_IDLE) begin
if(reset == 13) sd_cmd <= CMD_PRECHARGE;
if(reset == 2) sd_cmd <= CMD_LOAD_MODE;
end
end else begin
if(q <= STATE_CMD_START) begin
sd_addr <= addr[20:8];
sd_ba <= addr[22:21];
sd_dqm <= { !ds[1], !ds[0] };
end else
sd_addr <= { 4'b0010, addr[23], addr[7:0]};
if(q == STATE_IDLE) begin
if(we || oe) sd_cmd <= CMD_ACTIVE;
else sd_cmd <= CMD_AUTO_REFRESH;
end else if(q == STATE_CMD_CONT) begin
if(we) sd_cmd <= CMD_WRITE;
else if(oe) sd_cmd <= CMD_READ;
end
end
end
endmodule

View File

@@ -0,0 +1,107 @@
//
// sprite.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module sprite (
input clk,
input size16,
input [7:0] v_cnt,
input [7:0] h_cnt,
output [7:0] x,
// interface to read pixel data from memory
output [10:0] addr,
input [1:0] ds,
input [7:0] data,
output pixel_active,
output pixel_cmap,
output pixel_prio,
output [1:0] pixel_data,
input oam_wr,
input [1:0] oam_addr,
input [7:0] oam_di,
output [7:0] oam_do
);
// x position for priority detection. Invisible sprites are far to the right and
// have minimum priority
assign x = v_visible?x_pos:8'hff;
// register used to store pixel data for current line
reg [7:0] data0;
reg [7:0] data1;
always @(posedge clk) begin
if(ds[0]) data0 <= data;
if(ds[1]) data1 <= data;
end
wire [7:0] height = size16?8'd16:8'd8;
wire v_visible = (v_cnt + 8'd16 >= y_pos) && (v_cnt + 8'd16 < y_pos + height);
wire visible = v_visible && (h_cnt + 8'd8 >= x_pos) && (h_cnt < x_pos);
// x position within sprite, mirror horizontally if required
wire [2:0] col_n = h_cnt - x_pos;
wire [2:0] col = flags[1]?col_n:~col_n;
assign pixel_data = { data1[col], data0[col] };
assign pixel_active = (pixel_data != 0) && visible;
// y position within sprite, mirror vertically if required
wire [3:0] row_n = v_cnt - y_pos;
wire [3:0] row = flags[2]?~row_n:row_n;
// 16 pixel tall sprites use one more rwo counter bit and the lsb
// of the tile index is ignored
wire [10:0] addr8 = { tile , row[2:0]};
wire [10:0] addr16 = { tile[7:1] , row};
assign addr = size16?addr16:addr8;
assign pixel_cmap = flags[0];
assign pixel_prio = flags[3];
reg [7:0] y_pos;
reg [7:0] x_pos;
reg [7:0] tile;
reg [3:0] flags;
always @(posedge clk) begin
if(oam_wr) begin
case(oam_addr)
0: y_pos <= oam_di;
1: x_pos <= oam_di;
2: tile <= oam_di;
3: flags <= oam_di[7:4];
endcase
end
end
assign oam_do =
(oam_addr == 0)?y_pos:
(oam_addr == 1)?x_pos:
(oam_addr == 2)?tile:
{ flags, 4'h0 };
endmodule

View File

@@ -0,0 +1,100 @@
//
// sprite_sort.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module sprite_sort #(
parameter WIDTH = 40
)(
// system signals
input clk,
input load,
// sort
input [8*WIDTH-1:0] x,
output [6*WIDTH-1:0] idx
);
wire [7:0] in [WIDTH-1:0];
generate
genvar i;
// map 1d input array onto 2d work array
// and 2d result array into 1d output array
for(i=0;i<WIDTH;i=i+1) begin : input_map
assign in[i] = x[(8*i)+7:8*i];
assign idx[(6*i)+5:6*i] = index[i];
end
endgenerate
reg [5:0] index [WIDTH-1:0];
reg [7:0] values [WIDTH-1:0];
wire [WIDTH/2-1:0] swap0;
wire [7:0] int_val [WIDTH-1:0];
wire [5:0] int_idx [WIDTH-1:0];
wire [WIDTH/2-2:0] swap1;
wire [7:0] sort_val [WIDTH-1:0];
wire [5:0] sort_idx [WIDTH-1:0];
// sorting takes 10 clock cycles
reg [3:0] cnt;
always @(posedge clk) begin
if(load) cnt <= 4'd0;
if(cnt != 10) cnt <= cnt + 4'd1;
end
generate
// 1st stage
for(i=0;i<WIDTH/2;i=i+1) begin : stage1
assign swap0[i] = values[2*i+0] > values[2*i+1];
assign int_val[2*i+0] = swap0[i]?values[2*i+1]:values[2*i+0];
assign int_val[2*i+1] = swap0[i]?values[2*i+0]:values[2*i+1];
assign int_idx[2*i+0] = swap0[i]?index[2*i+1]:index[2*i+0];
assign int_idx[2*i+1] = swap0[i]?index[2*i+0]:index[2*i+1];
end
// 2nd stage
assign sort_val[0] = int_val[0];
assign sort_idx[0] = int_idx[0];
assign sort_val[WIDTH-1] = int_val[WIDTH-1];
assign sort_idx[WIDTH-1] = int_idx[WIDTH-1];
for(i=0;i<WIDTH/2-1;i=i+1) begin : stage4
assign swap1[i] = int_val[2*i+1] > int_val[2*i+2];
assign sort_val[2*i+1] = swap1[i]?int_val[2*i+2]:int_val[2*i+1];
assign sort_val[2*i+2] = swap1[i]?int_val[2*i+1]:int_val[2*i+2];
assign sort_idx[2*i+1] = swap1[i]?int_idx[2*i+2]:int_idx[2*i+1];
assign sort_idx[2*i+2] = swap1[i]?int_idx[2*i+1]:int_idx[2*i+2];
end
for(i=0;i<WIDTH;i=i+1) begin : advance
always @(posedge clk) begin
if(load) begin
values[i] <= in[i];
index[i] <= i;
end else begin
values[i] <= sort_val[i];
index[i] <= sort_idx[i];
end
end
end
endgenerate
endmodule

View File

@@ -0,0 +1,188 @@
//
// sprites.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module sprites (
input clk,
input size16,
// pixel position input which the current pixel is generated for
input [7:0] v_cnt,
input [7:0] h_cnt,
// pixel output
output pixel_active, // current pixel
output [1:0] pixel_data,
output pixel_cmap,
output pixel_prio,
input sort,
input [3:0] index, // index of sprite which video wants to read data for
output [10:0] addr,
input [1:0] dvalid,
input [7:0] data,
// oam memory interface
input oam_wr,
input [7:0] oam_addr,
input [7:0] oam_di,
output [7:0] oam_do
);
localparam SPRITES = 40;
// ------------------------------------------------------------------------
// ---------------------------- priority sorting --------------------------
// ------------------------------------------------------------------------
// sprites have priority from left to right and the leftmost 10 are
// being displayed. We thus need to sort them
wire [SPRITES*8-1:0] sprite_x;
wire [SPRITES*6-1:0] sprite_idx;
sprite_sort #(.WIDTH(SPRITES)) sprite_sort (
.clk ( clk ),
.load ( sort ), // begin of oam phase
.x ( sprite_x ),
.idx ( sprite_idx )
);
wire [SPRITES-1:0] sprite_pixel_active;
wire [SPRITES-1:0] sprite_pixel_cmap;
wire [SPRITES-1:0] sprite_pixel_prio;
wire [1:0] sprite_pixel_data [SPRITES-1:0];
wire [10:0] sprite_addr [SPRITES-1:0];
wire [7:0] sprite_oam_do [SPRITES-1:0];
assign oam_do = sprite_oam_do[oam_addr[7:2]];
// address where the sprite wants to read data from
wire [5:0] sprite_idx_array [SPRITES-1:0];
wire [5:0] prio_index = sprite_idx_array[index];
assign addr = sprite_addr[prio_index];
generate
genvar i;
for(i=0;i<SPRITES;i=i+1) begin : spr
// map 1d array to 2d array
assign sprite_idx_array[i] = sprite_idx[6*i+5:6*i];
sprite sprite (
.clk ( clk ),
.size16 ( size16 ),
.v_cnt ( v_cnt ),
.h_cnt ( h_cnt ),
.x ( sprite_x[(8*i)+7:(8*i)] ),
.addr ( sprite_addr[i] ),
.ds ( (prio_index == i)?dvalid:2'b00),
.data ( data ),
.pixel_cmap ( sprite_pixel_cmap[i] ),
.pixel_prio ( sprite_pixel_prio[i] ),
.pixel_active ( sprite_pixel_active[i] ),
.pixel_data ( sprite_pixel_data[i] ),
.oam_wr ( oam_wr && (oam_addr[7:2] == i) ),
.oam_addr ( oam_addr[1:0] ),
.oam_di ( oam_di ),
.oam_do ( sprite_oam_do[i] )
);
end
endgenerate
// ------------------------------------------------------------------------
// ---------------------------- priority display --------------------------
// ------------------------------------------------------------------------
// only the 10 leftmost sprites are potentially being displayed
// get the indices of the 10 leftmost sprites
wire [5:0] spr0 = sprite_idx_array[0];
wire [5:0] spr1 = sprite_idx_array[1];
wire [5:0] spr2 = sprite_idx_array[2];
wire [5:0] spr3 = sprite_idx_array[3];
wire [5:0] spr4 = sprite_idx_array[4];
wire [5:0] spr5 = sprite_idx_array[5];
wire [5:0] spr6 = sprite_idx_array[6];
wire [5:0] spr7 = sprite_idx_array[7];
wire [5:0] spr8 = sprite_idx_array[8];
wire [5:0] spr9 = sprite_idx_array[9];
// if any of these is active then the current pixel is being driven by
// the sprite engine
assign pixel_active =
sprite_pixel_active[spr0] ||
sprite_pixel_active[spr1] ||
sprite_pixel_active[spr2] ||
sprite_pixel_active[spr3] ||
sprite_pixel_active[spr4] ||
sprite_pixel_active[spr5] ||
sprite_pixel_active[spr6] ||
sprite_pixel_active[spr7] ||
sprite_pixel_active[spr8] ||
sprite_pixel_active[spr9];
// get the pixel information of the leftmost sprite
assign pixel_data =
sprite_pixel_active[spr0]?sprite_pixel_data[spr0]:
sprite_pixel_active[spr1]?sprite_pixel_data[spr1]:
sprite_pixel_active[spr2]?sprite_pixel_data[spr2]:
sprite_pixel_active[spr3]?sprite_pixel_data[spr3]:
sprite_pixel_active[spr4]?sprite_pixel_data[spr4]:
sprite_pixel_active[spr5]?sprite_pixel_data[spr5]:
sprite_pixel_active[spr6]?sprite_pixel_data[spr6]:
sprite_pixel_active[spr7]?sprite_pixel_data[spr7]:
sprite_pixel_active[spr8]?sprite_pixel_data[spr8]:
sprite_pixel_active[spr9]?sprite_pixel_data[spr9]:
2'b00;
// get the colormap of the leftmost sprite
assign pixel_cmap =
sprite_pixel_active[spr0]?sprite_pixel_cmap[spr0]:
sprite_pixel_active[spr1]?sprite_pixel_cmap[spr1]:
sprite_pixel_active[spr2]?sprite_pixel_cmap[spr2]:
sprite_pixel_active[spr3]?sprite_pixel_cmap[spr3]:
sprite_pixel_active[spr4]?sprite_pixel_cmap[spr4]:
sprite_pixel_active[spr5]?sprite_pixel_cmap[spr5]:
sprite_pixel_active[spr6]?sprite_pixel_cmap[spr6]:
sprite_pixel_active[spr7]?sprite_pixel_cmap[spr7]:
sprite_pixel_active[spr8]?sprite_pixel_cmap[spr8]:
sprite_pixel_active[spr9]?sprite_pixel_cmap[spr9]:
1'b0;
// get the priority of the leftmost sprite
assign pixel_prio =
sprite_pixel_active[spr0]?sprite_pixel_prio[spr0]:
sprite_pixel_active[spr1]?sprite_pixel_prio[spr1]:
sprite_pixel_active[spr2]?sprite_pixel_prio[spr2]:
sprite_pixel_active[spr3]?sprite_pixel_prio[spr3]:
sprite_pixel_active[spr4]?sprite_pixel_prio[spr4]:
sprite_pixel_active[spr5]?sprite_pixel_prio[spr5]:
sprite_pixel_active[spr6]?sprite_pixel_prio[spr6]:
sprite_pixel_active[spr7]?sprite_pixel_prio[spr7]:
sprite_pixel_active[spr8]?sprite_pixel_prio[spr8]:
sprite_pixel_active[spr9]?sprite_pixel_prio[spr9]:
1'b0;
endmodule

View File

@@ -0,0 +1,201 @@
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- Z80 compatible microprocessor core, synchronous top level with clock enable
-- Different timing than the original z80
-- Inputs needs to be synchronous and outputs may glitch
--
-- Version : 0240
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
-- 0235 : First release
--
-- 0236 : Added T2Write generic
--
-- 0237 : Fixed T2Write with wait state
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
entity GBse is
generic(
T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2
IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle
);
port(
RESET_n : in std_logic;
CLK_n : in std_logic;
CLKEN : in std_logic;
WAIT_n : in std_logic;
INT_n : in std_logic;
NMI_n : in std_logic;
BUSRQ_n : in std_logic;
M1_n : out std_logic;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : out std_logic;
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
A : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end GBse;
architecture rtl of GBse is
signal IntCycle_n : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal IORQ : std_logic;
signal DI_Reg : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
begin
u0 : T80
generic map
(
Mode => 3,
IOWait => IOWait,
Flag_S => 0,
Flag_P => 0,
Flag_X => 0,
Flag_Y => 0,
Flag_C => 4,
Flag_H => 5,
Flag_N => 6,
Flag_Z => 7
)
port map(
CEN => CLKEN,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => Wait_n,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK_n,
CLK_n => CLK_n,
A => A,
DInst => DI,
DI => DI_Reg,
DO => DO,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n);
process (RESET_n, CLK_n)
begin
if RESET_n = '0' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
DI_Reg <= "00000000";
elsif CLK_n'event and CLK_n = '1' then
if CLKEN = '1' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
if MCycle = "001" then
if TState = "001" or (TState = "010" and Wait_n = '0') then
RD_n <= not IntCycle_n;
MREQ_n <= not IntCycle_n;
IORQ_n <= IntCycle_n;
end if;
if TState = "011" then
MREQ_n <= '0';
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then
RD_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
if T2Write = 0 then
if TState = "010" and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
end if;
end if;
if TState = "010" and Wait_n = '1' then
DI_Reg <= DI;
end if;
end if;
end if;
end process;
end;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,371 @@
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- Z80 compatible microprocessor core
--
-- Version : 0247
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
--
-- 0238 : Fixed zero flag for 16 bit SBC and ADC
--
-- 0240 : Added GB operations
--
-- 0242 : Cleanup
--
-- 0247 : Cleanup
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity T80_ALU is
generic(
Mode : integer := 0;
Flag_C : integer := 0;
Flag_N : integer := 1;
Flag_P : integer := 2;
Flag_X : integer := 3;
Flag_H : integer := 4;
Flag_Y : integer := 5;
Flag_Z : integer := 6;
Flag_S : integer := 7
);
port(
Arith16 : in std_logic;
Z16 : in std_logic;
ALU_Op : in std_logic_vector(3 downto 0);
IR : in std_logic_vector(5 downto 0);
ISet : in std_logic_vector(1 downto 0);
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
F_In : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0)
);
end T80_ALU;
architecture rtl of T80_ALU is
procedure AddSub(A : std_logic_vector;
B : std_logic_vector;
Sub : std_logic;
Carry_In : std_logic;
signal Res : out std_logic_vector;
signal Carry : out std_logic) is
variable B_i : unsigned(A'length - 1 downto 0);
variable Res_i : unsigned(A'length + 1 downto 0);
begin
if Sub = '1' then
B_i := not unsigned(B);
else
B_i := unsigned(B);
end if;
Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
Carry <= Res_i(A'length + 1);
Res <= std_logic_vector(Res_i(A'length downto 1));
end;
-- AddSub variables (temporary signals)
signal UseCarry : std_logic;
signal Carry7_v : std_logic;
signal Overflow_v : std_logic;
signal HalfCarry_v : std_logic;
signal Carry_v : std_logic;
signal Q_v : std_logic_vector(7 downto 0);
signal BitMask : std_logic_vector(7 downto 0);
begin
with IR(5 downto 3) select BitMask <= "00000001" when "000",
"00000010" when "001",
"00000100" when "010",
"00001000" when "011",
"00010000" when "100",
"00100000" when "101",
"01000000" when "110",
"10000000" when others;
UseCarry <= not ALU_Op(2) and ALU_Op(0);
AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
-- bug fix - parity flag is just parity for 8080, also overflow for Z80
process (Carry_v, Carry7_v, Q_v)
begin
if(Mode=2) then
OverFlow_v <= not (Q_v(0) xor Q_v(1) xor Q_v(2) xor Q_v(3) xor
Q_v(4) xor Q_v(5) xor Q_v(6) xor Q_v(7)); else
OverFlow_v <= Carry_v xor Carry7_v;
end if;
end process;
process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
variable Q_t : std_logic_vector(7 downto 0);
variable DAA_Q : unsigned(8 downto 0);
begin
Q_t := "--------";
F_Out <= F_In;
DAA_Q := "---------";
case ALU_Op is
when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" =>
F_Out(Flag_N) <= '0';
F_Out(Flag_C) <= '0';
case ALU_OP(2 downto 0) is
when "000" | "001" => -- ADD, ADC
Q_t := Q_v;
F_Out(Flag_C) <= Carry_v;
F_Out(Flag_H) <= HalfCarry_v;
F_Out(Flag_P) <= OverFlow_v;
when "010" | "011" | "111" => -- SUB, SBC, CP
Q_t := Q_v;
F_Out(Flag_N) <= '1';
F_Out(Flag_C) <= not Carry_v;
F_Out(Flag_H) <= not HalfCarry_v;
F_Out(Flag_P) <= OverFlow_v;
when "100" => -- AND
Q_t(7 downto 0) := BusA and BusB;
F_Out(Flag_H) <= '1';
when "101" => -- XOR
Q_t(7 downto 0) := BusA xor BusB;
F_Out(Flag_H) <= '0';
when others => -- OR "110"
Q_t(7 downto 0) := BusA or BusB;
F_Out(Flag_H) <= '0';
end case;
if ALU_Op(2 downto 0) = "111" then -- CP
F_Out(Flag_X) <= BusB(3);
F_Out(Flag_Y) <= BusB(5);
else
F_Out(Flag_X) <= Q_t(3);
F_Out(Flag_Y) <= Q_t(5);
end if;
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
if Z16 = '1' then
F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC
end if;
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_S) <= Q_t(7);
case ALU_Op(2 downto 0) is
when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP
when others =>
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
end case;
if Arith16 = '1' then
F_Out(Flag_S) <= F_In(Flag_S);
F_Out(Flag_Z) <= F_In(Flag_Z);
F_Out(Flag_P) <= F_In(Flag_P);
end if;
when "1100" =>
-- DAA
F_Out(Flag_H) <= F_In(Flag_H);
F_Out(Flag_C) <= F_In(Flag_C);
DAA_Q(7 downto 0) := unsigned(BusA);
DAA_Q(8) := '0';
if F_In(Flag_N) = '0' then
-- After addition
-- Alow > 9 or H = 1
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
if (DAA_Q(3 downto 0) > 9) then
F_Out(Flag_H) <= '1';
else
F_Out(Flag_H) <= '0';
end if;
DAA_Q := DAA_Q + 6;
end if;
-- new Ahigh > 9 or C = 1
if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then
DAA_Q := DAA_Q + 96; -- 0x60
end if;
else
-- After subtraction
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
if DAA_Q(3 downto 0) > 5 then
F_Out(Flag_H) <= '0';
end if;
DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6;
end if;
if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then
DAA_Q := DAA_Q - 352; -- 0x160
end if;
end if;
F_Out(Flag_X) <= DAA_Q(3);
F_Out(Flag_Y) <= DAA_Q(5);
F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8);
Q_t := std_logic_vector(DAA_Q(7 downto 0));
if DAA_Q(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_S) <= DAA_Q(7);
F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor
DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7));
when "1101" | "1110" =>
-- RLD, RRD
Q_t(7 downto 4) := BusA(7 downto 4);
if ALU_Op(0) = '1' then
Q_t(3 downto 0) := BusB(7 downto 4);
else
Q_t(3 downto 0) := BusB(3 downto 0);
end if;
F_Out(Flag_H) <= '0';
F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= Q_t(3);
F_Out(Flag_Y) <= Q_t(5);
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_S) <= Q_t(7);
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
when "1001" =>
-- BIT
Q_t(7 downto 0) := BusB and BitMask;
F_Out(Flag_S) <= Q_t(7);
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
F_Out(Flag_P) <= '1';
else
F_Out(Flag_Z) <= '0';
F_Out(Flag_P) <= '0';
end if;
F_Out(Flag_H) <= '1';
F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= '0';
F_Out(Flag_Y) <= '0';
if IR(2 downto 0) /= "110" then
F_Out(Flag_X) <= BusB(3);
F_Out(Flag_Y) <= BusB(5);
end if;
when "1010" =>
-- SET
Q_t(7 downto 0) := BusB or BitMask;
when "1011" =>
-- RES
Q_t(7 downto 0) := BusB and not BitMask;
when "1000" =>
-- ROT
case IR(5 downto 3) is
when "000" => -- RLC
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := BusA(7);
F_Out(Flag_C) <= BusA(7);
when "010" => -- RL
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := F_In(Flag_C);
F_Out(Flag_C) <= BusA(7);
when "001" => -- RRC
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := BusA(0);
F_Out(Flag_C) <= BusA(0);
when "011" => -- RR
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := F_In(Flag_C);
F_Out(Flag_C) <= BusA(0);
when "100" => -- SLA
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := '0';
F_Out(Flag_C) <= BusA(7);
when "110" => -- SLL (Undocumented) / SWAP
if Mode = 3 then
Q_t(7 downto 4) := BusA(3 downto 0);
Q_t(3 downto 0) := BusA(7 downto 4);
F_Out(Flag_C) <= '0';
else
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := '1';
F_Out(Flag_C) <= BusA(7);
end if;
when "101" => -- SRA
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := BusA(7);
F_Out(Flag_C) <= BusA(0);
when others => -- SRL
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := '0';
F_Out(Flag_C) <= BusA(0);
end case;
F_Out(Flag_H) <= '0';
F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= Q_t(3);
F_Out(Flag_Y) <= Q_t(5);
F_Out(Flag_S) <= Q_t(7);
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
if ISet = "00" then
F_Out(Flag_P) <= F_In(Flag_P);
F_Out(Flag_S) <= F_In(Flag_S);
F_Out(Flag_Z) <= F_In(Flag_Z);
end if;
when others =>
null;
end case;
Q <= Q_t;
end process;
end;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,228 @@
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- Z80 compatible microprocessor core
--
-- Version : 0242
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t80/
--
-- Limitations :
--
-- File history :
--
library IEEE;
use IEEE.std_logic_1164.all;
package T80_Pack is
constant aNone : std_logic_vector(2 downto 0) := "111";
constant aBC : std_logic_vector(2 downto 0) := "000";
constant aDE : std_logic_vector(2 downto 0) := "001";
constant aXY : std_logic_vector(2 downto 0) := "010";
constant aIOA : std_logic_vector(2 downto 0) := "100";
constant aSP : std_logic_vector(2 downto 0) := "101";
constant aZI : std_logic_vector(2 downto 0) := "110";
component T80
generic(
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle
Flag_C : integer := 0;
Flag_N : integer := 1;
Flag_P : integer := 2;
Flag_X : integer := 3;
Flag_H : integer := 4;
Flag_Y : integer := 5;
Flag_Z : integer := 6;
Flag_S : integer := 7
);
port(
RESET_n : in std_logic;
CLK_n : in std_logic;
CEN : in std_logic;
WAIT_n : in std_logic;
INT_n : in std_logic;
NMI_n : in std_logic;
BUSRQ_n : in std_logic;
M1_n : out std_logic;
IORQ : out std_logic;
NoRead : out std_logic;
Write : out std_logic;
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
A : out std_logic_vector(15 downto 0);
DInst : in std_logic_vector(7 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
MC : out std_logic_vector(2 downto 0);
TS : out std_logic_vector(2 downto 0);
IntCycle_n : out std_logic;
IntE : out std_logic;
Stop : out std_logic
);
end component;
component T80_Reg
port(
Clk : in std_logic;
CEN : in std_logic;
WEH : in std_logic;
WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0)
);
end component;
component T80_MCode
generic(
Mode : integer := 0;
Flag_C : integer := 0;
Flag_N : integer := 1;
Flag_P : integer := 2;
Flag_X : integer := 3;
Flag_H : integer := 4;
Flag_Y : integer := 5;
Flag_Z : integer := 6;
Flag_S : integer := 7
);
port(
IR : in std_logic_vector(7 downto 0);
ISet : in std_logic_vector(1 downto 0);
MCycle : in std_logic_vector(2 downto 0);
F : in std_logic_vector(7 downto 0);
NMICycle : in std_logic;
IntCycle : in std_logic;
XY_State : in std_logic_vector(1 downto 0);
MCycles : out std_logic_vector(2 downto 0);
TStates : out std_logic_vector(2 downto 0);
Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD
Inc_PC : out std_logic;
Inc_WZ : out std_logic;
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
Read_To_Reg : out std_logic;
Read_To_Acc : out std_logic;
Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
ALU_Op : out std_logic_vector(3 downto 0);
-- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
Save_ALU : out std_logic;
PreserveC : out std_logic;
Arith16 : out std_logic;
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
IORQ : out std_logic;
Jump : out std_logic;
JumpE : out std_logic;
JumpXY : out std_logic;
Call : out std_logic;
RstP : out std_logic;
LDZ : out std_logic;
LDW : out std_logic;
LDSPHL : out std_logic;
Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
ExchangeDH : out std_logic;
ExchangeRp : out std_logic;
ExchangeAF : out std_logic;
ExchangeRS : out std_logic;
I_DJNZ : out std_logic;
I_CPL : out std_logic;
I_CCF : out std_logic;
I_SCF : out std_logic;
I_RETN : out std_logic;
I_BT : out std_logic;
I_BC : out std_logic;
I_BTR : out std_logic;
I_RLD : out std_logic;
I_RRD : out std_logic;
I_INRC : out std_logic;
SetDI : out std_logic;
SetEI : out std_logic;
IMode : out std_logic_vector(1 downto 0);
Halt : out std_logic;
NoRead : out std_logic;
Write : out std_logic;
XYbit_undoc : out std_logic
);
end component;
component T80_ALU
generic(
Mode : integer := 0;
Flag_C : integer := 0;
Flag_N : integer := 1;
Flag_P : integer := 2;
Flag_X : integer := 3;
Flag_H : integer := 4;
Flag_Y : integer := 5;
Flag_Z : integer := 6;
Flag_S : integer := 7
);
port(
Arith16 : in std_logic;
Z16 : in std_logic;
ALU_Op : in std_logic_vector(3 downto 0);
IR : in std_logic_vector(5 downto 0);
ISet : in std_logic_vector(1 downto 0);
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
F_In : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0)
);
end component;
end;

View File

@@ -0,0 +1,114 @@
-- ****
-- T80(b) core. In an effort to merge and maintain bug fixes ....
--
--
-- Ver 300 started tidyup
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
--
-- ****
--
-- T80 Registers, technology independent
--
-- Version : 0244
--
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-- The latest version of this file can be found at:
-- http://www.opencores.org/cvsweb.shtml/t51/
--
-- Limitations :
--
-- File history :
--
-- 0242 : Initial release
--
-- 0244 : Changed to single register file
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity T80_Reg is
port(
Clk : in std_logic;
CEN : in std_logic;
WEH : in std_logic;
WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0)
);
end T80_Reg;
architecture rtl of T80_Reg is
type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0);
signal RegsH : Register_Image(0 to 7);
signal RegsL : Register_Image(0 to 7);
begin
process (Clk)
begin
if Clk'event and Clk = '1' then
if CEN = '1' then
if WEH = '1' then
RegsH(to_integer(unsigned(AddrA))) <= DIH;
end if;
if WEL = '1' then
RegsL(to_integer(unsigned(AddrA))) <= DIL;
end if;
end if;
end if;
end process;
DOAH <= RegsH(to_integer(unsigned(AddrA)));
DOAL <= RegsL(to_integer(unsigned(AddrA)));
DOBH <= RegsH(to_integer(unsigned(AddrB)));
DOBL <= RegsL(to_integer(unsigned(AddrB)));
DOCH <= RegsH(to_integer(unsigned(AddrC)));
DOCL <= RegsL(to_integer(unsigned(AddrC)));
end;

View File

@@ -0,0 +1,103 @@
//
// timer.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module timer (
input reset,
input clk, // 4 Mhz cpu clock
output reg irq,
// cpu register interface
input cpu_sel,
input [1:0] cpu_addr,
input cpu_wr,
input [7:0] cpu_di,
output [7:0] cpu_do
);
// input: 4Mhz
// clk_div[0] = 2Mhz
// clk_div[1] = 1Mhz
// clk_div[2] = 524khz
// clk_div[3] = 262khz
// clk_div[4] = 131khz
// clk_div[5] = 65khz
// clk_div[6] = 32khz
// clk_div[7] = 16khz
// clk_div[8] = 8khz
// clk_div[9] = 4khz
reg [9:0] clk_div;
always @(posedge clk)
clk_div <= clk_div + 10'd1;
reg [7:0] div;
reg [7:0] tma;
reg [7:0] tima;
reg [2:0] tac;
always @(posedge clk) begin
if(reset) begin
tima <= 8'h00;
tma <= 8'h00;
tac <= 8'h00;
irq <= 1'b0;
end else begin
irq <= 1'b0;
if(clk_div[7:0] == 0) // 16kHz
div <= div + 8'd1;
// timer enabled?
if(tac[2]) begin
// timer frequency
if(((tac[1:0] == 2'b00) && (clk_div[9:0] == 0)) || // 4 khz
((tac[1:0] == 2'b01) && (clk_div[3:0] == 0)) || // 262 khz
((tac[1:0] == 2'b10) && (clk_div[5:0] == 0)) || // 65 khz
((tac[1:0] == 2'b11) && (clk_div[7:0] == 0))) begin // 16 khz
if(tima != 8'hff)
tima <= tima + 8'd1;
else begin
irq <= 1'b1; // irq when timer overflows
tima <= tma; // reload timer
end
end
end
if(cpu_sel && cpu_wr) begin
case(cpu_addr)
2'b00: div <= 8'h00; // writing clears counter
2'b01: tima <= cpu_di;
2'b10: tma <= cpu_di;
2'b11: tac <= cpu_di[2:0];
endcase
end
end
end
assign cpu_do =
(cpu_addr == 2'b00)?div:
(cpu_addr == 2'b01)?tima:
(cpu_addr == 2'b10)?tma:
{5'b00000, tac};
endmodule

View File

@@ -0,0 +1,513 @@
//
// video.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 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/>.
//
module video (
input reset,
input clk, // 4 Mhz cpu clock
// cpu register adn oam interface
input cpu_sel_oam,
input cpu_sel_reg,
input [7:0] cpu_addr,
input cpu_wr,
input [7:0] cpu_di,
output [7:0] cpu_do,
// output to lcd
output lcd_on,
output lcd_clkena,
output [1:0] lcd_data,
output reg irq,
// vram connection
output [1:0] mode,
output vram_rd,
output [12:0] vram_addr,
input [7:0] vram_data,
// dma connection
output dma_rd,
output [15:0] dma_addr,
input [7:0] dma_data
);
localparam STAGE2 = 9'd250; // oam + disp + pause
localparam OAM_LEN = 80;
wire sprite_pixel_active;
wire [1:0] sprite_pixel_data;
wire sprite_pixel_cmap;
wire sprite_pixel_prio;
wire [7:0] oam_do;
wire [3:0] sprite_index = h_cnt[7:4]-(OAM_LEN/16); // memory io starts at h_cnt == 16
wire [10:0] sprite_addr;
// "data strobe" for the two bytes each sprite line consists of
wire [1:0] sprite_dvalid = {
(h_cnt[3:0] == 4'hf) && !vblank && !hblank,
(h_cnt[3:0] == 4'h7) && !vblank && !hblank };
sprites sprites (
.clk ( clk ),
.size16 ( lcdc_spr_siz ),
.v_cnt ( v_cnt ),
.h_cnt ( h_cnt-STAGE2 ), // sprites are added in second stage
.sort ( h_cnt == 0 ), // start of oam phase
.pixel_active ( sprite_pixel_active ),
.pixel_data ( sprite_pixel_data ),
.pixel_cmap ( sprite_pixel_cmap ),
.pixel_prio ( sprite_pixel_prio ),
.index ( sprite_index ),
.addr ( sprite_addr ),
.dvalid ( sprite_dvalid),
.data ( vram_data ),
.oam_wr ( oam_wr ),
.oam_addr ( oam_addr ),
.oam_di ( oam_di ),
.oam_do ( oam_do )
);
// give dma access to oam
wire [7:0] oam_addr = dma_active?dma_addr[7:0]:cpu_addr;
wire oam_wr = dma_active?(dma_cnt[1:0] == 2):(cpu_wr && cpu_sel_oam);
wire [7:0] oam_di = dma_active?dma_data:cpu_di;
assign lcd_on = lcdc_on;
// $ff40 LCDC
wire lcdc_on = lcdc[7];
wire lcdc_win_tile_map_sel = lcdc[6];
wire lcdc_win_ena = lcdc[5];
wire lcdc_tile_data_sel = lcdc[4];
wire lcdc_bg_tile_map_sel = lcdc[3];
wire lcdc_spr_siz = lcdc[2];
wire lcdc_spr_ena = lcdc[1];
wire lcdc_bg_ena = lcdc[0];
reg [7:0] lcdc;
// ff41 STAT
reg [7:0] stat;
// ff42, ff43 background scroll registers
reg [7:0] scy;
reg [7:0] scy_r; // stable over entire image
reg [7:0] scx;
reg [7:0] scx_r; // stable over line
// ff44 line counter
reg [7:0] ly;
// ff45 line counter compare
wire lyc_match = (ly == lyc);
reg [7:0] lyc;
reg [7:0] bgp;
reg [7:0] obp0;
reg [7:0] obp1;
reg [7:0] wy;
reg [7:0] wy_r; // stable over entire image
reg [7:0] wx;
reg [7:0] wx_r; // stable over line
// --------------------------------------------------------------------
// ----------------------------- DMA engine ---------------------------
// --------------------------------------------------------------------
assign dma_addr = { dma, dma_cnt[9:2] };
assign dma_rd = dma_active;
reg dma_active;
reg [7:0] dma;
reg [9:0] dma_cnt; // dma runs 4*160 clock cycles = 160us @ 4MHz
always @(posedge clk) begin
if(reset)
dma_active <= 1'b0;
else begin
// writing the dma register engages the dma engine
if(cpu_sel_reg && cpu_wr && (cpu_addr[3:0] == 4'h6)) begin
dma_active <= 1'b1;
dma_cnt <= 10'd0;
end else if(dma_cnt != 160*4-1)
dma_cnt <= dma_cnt + 10'd1;
else
dma_active <= 1'b0;
end
end
// --------------------------------------------------------------------
// ------------------------------- IRQs -------------------------------
// --------------------------------------------------------------------
always @(posedge clk) begin
irq <= 1'b0;
// lyc=ly coincidence
if(stat[6] && (h_cnt == 0) && lyc_match)
irq <= 1'b1;
// begin of oam phase
if(stat[5] && (h_cnt == 0))
irq <= 1'b1;
// begin of vblank
if(stat[4] && (h_cnt == 455) && (v_cnt == 143))
irq <= 1'b1;
// begin of hblank
if(stat[3] && (h_cnt == OAM_LEN + 160 + hextra))
irq <= 1'b1;
end
// --------------------------------------------------------------------
// --------------------- CPU register interface -----------------------
// --------------------------------------------------------------------
always @(posedge clk) begin
if(reset) begin
lcdc <= 8'h00; // screen must be off since dmg rom writes to vram
scy <= 8'h00;
scx <= 8'h00;
wy <= 8'h00;
wx <= 8'h00;
bgp <= 8'hfc;
obp0 <= 8'hff;
obp1 <= 8'hff;
end else begin
if(cpu_sel_reg && cpu_wr) begin
case(cpu_addr[3:0])
4'h0: lcdc <= cpu_di;
4'h1: stat <= cpu_di;
4'h2: scy <= cpu_di;
4'h3: scx <= cpu_di;
// a write to 4 is supposed to reset the v_cnt
4'h5: lyc <= cpu_di;
4'h6: dma <= cpu_di;
4'h7: bgp <= cpu_di;
4'h8: obp0 <= cpu_di;
4'h9: obp1 <= cpu_di;
4'ha: wy <= cpu_di;
4'hb: wx <= cpu_di;
endcase
end
end
end
assign cpu_do =
cpu_sel_oam?oam_do:
(cpu_addr[3:0] == 4'h0)?lcdc:
(cpu_addr[3:0] == 4'h1)?{stat[7:3], lyc_match, mode}:
(cpu_addr[3:0] == 4'h2)?scy:
(cpu_addr[3:0] == 4'h3)?scx:
(cpu_addr[3:0] == 4'h4)?ly:
(cpu_addr[3:0] == 4'h5)?lyc:
(cpu_addr[3:0] == 4'h6)?dma:
(cpu_addr[3:0] == 4'h7)?bgp:
(cpu_addr[3:0] == 4'h8)?obp0:
(cpu_addr[3:0] == 4'h9)?obp1:
(cpu_addr[3:0] == 4'ha)?wy:
(cpu_addr[3:0] == 4'hb)?wx:
8'hff;
// --------------------------------------------------------------------
// ----------------- second output stage: sprites ---------------------
// --------------------------------------------------------------------
assign lcd_data = stage2_data;
assign lcd_clkena = stage2_clkena;
reg [1:0] stage2_data;
reg stage2_clkena;
reg [1:0] stage2_buffer [159:0];
reg [7:0] stage2_wptr;
reg [7:0] stage2_rptr;
// apply bg palette
wire [1:0] stage2_bg_pix = (!lcdc_bg_ena && !window_ena)?2'b11: // background off?
(stage2_buffer[stage2_rptr] == 2'b00)?bgp[1:0]:
(stage2_buffer[stage2_rptr] == 2'b01)?bgp[3:2]:
(stage2_buffer[stage2_rptr] == 2'b10)?bgp[5:4]:
bgp[7:6];
// apply sprite palette
wire [7:0] obp = sprite_pixel_cmap?obp1:obp0;
wire [1:0] sprite_pix =
(sprite_pixel_data == 2'b00)?obp[1:0]:
(sprite_pixel_data == 2'b01)?obp[3:2]:
(sprite_pixel_data == 2'b10)?obp[5:4]:
obp[7:6];
// a sprite pixel is visible if
// - sprites are enabled
// - there's a sprite at the current position
// - the sprites prioroty bit is 0, or
// - the prites priority is 1 and the backrgound color is 00
wire sprite_pixel_visible =
sprite_pixel_active && lcdc_spr_ena &&
((!sprite_pixel_prio) || (stage2_buffer[stage2_rptr] == 2'b00));
always @(posedge clk) begin
if(h_cnt == 455) begin
stage2_wptr <= 8'h00;
stage2_rptr <= 8'h00;
end
if(stage1_clkena) begin
stage2_buffer[stage2_wptr] <= stage1_data;
stage2_wptr <= stage2_wptr + 8'd1;
end
stage2_clkena = !vblank && stage2;
if(stage2) begin
// mix sprites and bg
if(sprite_pixel_visible) stage2_data <= sprite_pix;
else stage2_data <= stage2_bg_pix;
stage2_rptr <= stage2_rptr + 8'd1;
end
end
// --------------------------------------------------------------------
// --------------- first output stage: bg and window ------------------
// --------------------------------------------------------------------
reg window_ena;
// output shift registers for both video data bits
reg [7:0] tile_shift_0;
reg [7:0] tile_shift_1;
reg [7:0] bg_tile;
reg [7:0] bg_tile_data0;
reg [7:0] bg_tile_data1;
wire stage1_clkena = !vblank && hdvalid;
wire [1:0] stage1_data = { tile_shift_1[7], tile_shift_0[7] };
// read data half a clock cycle after ram has been selected
always @(posedge clk) begin
// every memory access is two pixel cycles
if(h_cnt[0]) begin
if(bg_tile_map_rd) bg_tile <= vram_data;
if(bg_tile_data0_rd) bg_tile_data0 <= vram_data;
if(bg_tile_data1_rd) bg_tile_data1 <= vram_data;
// sprite data is evaluated inside the sprite engine
end
// shift bg/window pixels out
if(bg_tile_obj_rd && h_cnt[0]) begin
tile_shift_0 <= bg_tile_data0;
tile_shift_1 <= bg_tile_data1;
end else begin
tile_shift_0 <= { tile_shift_0[6:0], 1'b0 };
tile_shift_1 <= { tile_shift_1[6:0], 1'b0 };
end
end
assign vram_rd = lcdc_on && (bg_tile_map_rd || bg_tile_data0_rd ||
bg_tile_data1_rd || bg_tile_obj_rd);
wire bg_tile_a12 = !lcdc_tile_data_sel?(~bg_tile[7]):1'b0;
wire tile_map_sel = window_ena?lcdc_win_tile_map_sel:lcdc_bg_tile_map_sel;
assign vram_addr =
bg_tile_map_rd?{2'b11, tile_map_sel, bg_tile_map_addr}:
bg_tile_data0_rd?{bg_tile_a12, bg_tile, tile_line, 1'b0}:
bg_tile_data1_rd?{bg_tile_a12, bg_tile, tile_line, 1'b1}:
{1'b0, sprite_addr, h_cnt[3]};
reg [9:0] bg_tile_map_addr;
wire vblank = (v_cnt >= 144);
// x scroll & 7 needs one more memory read per line
reg [1:0] hextra_tiles;
wire [7:0] hextra = { 3'b000, hextra_tiles, 3'b000 };
wire hblank = ((h_cnt < OAM_LEN) || (h_cnt >= 160+OAM_LEN+hextra));
wire oam = (h_cnt < OAM_LEN); // 80 clocks oam
wire stage2 = ((h_cnt >= STAGE2) && (h_cnt < STAGE2+160)); // output out of stage2
// first valid pixels are delivered 8 clocks after end of hblank
// wire hdvalid = ((h_cnt >= OAM_LEN+8) && (h_cnt < 160+OAM_LEN+8));
wire hdvalid = de;
reg de;
reg [7:0] skip;
reg [7:0] pcnt;
localparam STATE_HBLANK = 0;
localparam STATE_OAM = 1;
localparam STATE_ACTIVE = 2;
always @(negedge clk) begin
if(h_cnt == 455) begin
// end of line
de <= 1'b0;
hextra_tiles <= 2'd0;
pcnt <= 8'd0;
skip <= 8'd0;
end else if(h_cnt == OAM_LEN) begin
// start of line
// skip entire oam time plus time until first data is delivered plus
// time to skip the pixels according to the horizontal scroll position
// (or the window start if line starts with window)
if(lcdc_win_ena && (v_cnt >= wy_r) && (wx_r < 8))
skip <= 8'd8 + (8'd7 - wx_r) - 8'd1;
else
skip <= 8'd8 + scx_r[2:0] - 8'd1;
// calculate how many extra tiles will have to be read in this line
if(lcdc_win_ena && (v_cnt >= wy_r) && (wx_r < 168)) begin
// window needs at least one extra cycle, two if bg scroll position or
// window are not 8 pixel aligned
if((wx_r[2:0] != 3'd7) || (scx_r[2:0] != 3'd0)) begin
if(wx_r[2:0] > ~scx_r[2:0])
hextra_tiles <= 2'd3;
else
hextra_tiles <= 2'd2;
end else
hextra_tiles <= 2'd1;
end else
if(scx_r[2:0] != 3'd0)
hextra_tiles <= 2'd1;
end else begin
if(win_start) begin
// if window starts skip until end of current cycle and skip
// pixels until new window data is ready
skip <= { 5'b00000 ,~h_cnt[2:0] } + 8'd8;
de <= 1'b0;
end
if(skip) skip <= skip - 8'd1;
// (re-)enable display at the end of the wait phase
if(skip == 1)
de <= 1'b1;
if(de) begin
if(pcnt != 160)
pcnt <= pcnt + 8'd1;
else
de <= 1'b0;
end
end
end
// cycle through the B01s states
wire bg_tile_map_rd = (!vblank) && (!hblank) && (h_cnt[2:1] == 2'b00);
wire bg_tile_data0_rd = (!vblank) && (!hblank) && (h_cnt[2:1] == 2'b01);
wire bg_tile_data1_rd = (!vblank) && (!hblank) && (h_cnt[2:1] == 2'b10);
wire bg_tile_obj_rd = (!vblank) && (!hblank) && (h_cnt[2:1] == 2'b11);
// Mode 00: h-blank
// Mode 01: v-blank
// Mode 10: oam
// Mode 11: oam and vram
assign mode =
vblank?2'b01:
oam?2'b10:
hblank?2'b00:
2'b11;
reg [8:0] h_cnt; // max 455
reg [7:0] v_cnt; // max 153
// line inside the background/window currently being drawn
wire [7:0] win_line = v_cnt - wy_r;
wire [7:0] bg_line = v_cnt + scy_r;
wire [2:0] tile_line = window_ena?win_line[2:0]:bg_line[2:0];
wire win_start = lcdc_win_ena && (v_cnt >= wy_r) && de && (wx_r >= 7) && (pcnt == wx_r-8);
// each memory access takes two cycles
always @(negedge clk) begin
// this ly change h_cnt is wrong!!!
if(h_cnt == 0)
ly <= (v_cnt >= 153)?(v_cnt-8'd153):(v_cnt+8'd1);
if(h_cnt != 455) begin
h_cnt <= h_cnt + 9'd1;
// make sure sginals don't change during the line
// latch at latest possible moment (one clock before display starts)
if(h_cnt == OAM_LEN-2) begin
scx_r <= scx;
wx_r <= wx;
scy_r <= scy;
end
// increment address at the end of each 8-pixel-cycle. But don't
// increment while waiting for current cycle to end due to window start
if(!hblank && h_cnt[2:0] == 3'b111 && (skip <= 8))
bg_tile_map_addr[4:0] <= bg_tile_map_addr[4:0] + 10'd1;
// begin of line
if(h_cnt == OAM_LEN-1) begin
// set tile map address for this line, assume there is no window
bg_tile_map_addr[9:5] <= bg_line[7:3];
bg_tile_map_addr[4:0] <= scx_r[7:3];
// special case wx < 8: line starts with window, no background
// visible at all
if(lcdc_win_ena && (v_cnt >= wy_r) && (wx_r < 8)) begin
window_ena <= 1'b1;
bg_tile_map_addr[9:5] <= win_line[7:3];
bg_tile_map_addr[4:0] <= 5'd0; // window always start with its very left
end
end
// check if the window starts here
if(win_start) begin
window_ena <= 1'b1;
bg_tile_map_addr[9:5] <= win_line[7:3];
bg_tile_map_addr[4:0] <= 5'd0; // window always start with its very left
end
end else begin
window_ena <= 1'b0; // next line starts with background
// end of line reached
h_cnt <= 9'd0;
if(v_cnt != 153)
v_cnt <= v_cnt + 8'd1;
else begin
// start of new image
v_cnt <= 8'd0;
// make sure sginals don't change during the image
wy_r <= wy;
end
end
end
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'd4,
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

View File

@@ -0,0 +1,172 @@
// megafunction wizard: %RAM: 1-PORT%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altsyncram
// ============================================================
// File Name: vram.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 vram (
address,
clock,
data,
wren,
q);
input [12:0] address;
input clock;
input [7:0] data;
input wren;
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),
.data_a (data),
.wren_a (wren),
.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_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 = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 8192,
altsyncram_component.operation_mode = "SINGLE_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
altsyncram_component.widthad_a = 13,
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 "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: Clken NUMERIC "0"
// 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 "8192"
// 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 "0"
// 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 "13"
// 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 "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
// 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 "8192"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
// 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 "13"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL "address[12..0]"
// 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 13 0 address 0 0 13 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 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 vram.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL vram.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL vram.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL vram.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL vram_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL vram_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,172 @@
// megafunction wizard: %RAM: 1-PORT%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altsyncram
// ============================================================
// File Name: zpram.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 zpram (
address,
clock,
data,
wren,
q);
input [7:0] address;
input clock;
input [7:0] data;
input wren;
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),
.data_a (data),
.wren_a (wren),
.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_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 = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.operation_mode = "SINGLE_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_reg_a = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
altsyncram_component.widthad_a = 8,
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 "0"
// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
// Retrieval info: PRIVATE: Clken NUMERIC "0"
// 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 "256"
// 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 "0"
// 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 "8"
// 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 "BYPASS"
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
// 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 "256"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
// 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 "8"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
// Retrieval info: USED_PORT: address 0 0 8 0 INPUT NODEFVAL "address[7..0]"
// 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 8 0 address 0 0 8 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 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 zpram.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL zpram_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf