1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-03-26 01:55:55 +00:00

new Core Arkanoid

This commit is contained in:
Gehstock
2018-12-04 06:29:23 +01:00
parent e52cc3faaf
commit 2b8582820b
77 changed files with 6488 additions and 2 deletions

View File

Before

Width:  |  Height:  |  Size: 998 KiB

After

Width:  |  Height:  |  Size: 998 KiB

View File

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

View File

@@ -0,0 +1,165 @@
# -------------------------------------------------------------------------- #
#
# 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.0.1 Build 232 06/12/2013 Service Pack 1 SJ Full Version
# Date created = 14:04:08 November 24, 2018
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# Centipede_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 16.1.2
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "01:53:30 APRIL 20, 2017"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
# Pin & Location Assignments
# ==========================
set_location_assignment PIN_7 -to LED
set_location_assignment PIN_54 -to CLOCK_27
set_location_assignment PIN_144 -to VGA_R[5]
set_location_assignment PIN_143 -to VGA_R[4]
set_location_assignment PIN_142 -to VGA_R[3]
set_location_assignment PIN_141 -to VGA_R[2]
set_location_assignment PIN_137 -to VGA_R[1]
set_location_assignment PIN_135 -to VGA_R[0]
set_location_assignment PIN_133 -to VGA_B[5]
set_location_assignment PIN_132 -to VGA_B[4]
set_location_assignment PIN_125 -to VGA_B[3]
set_location_assignment PIN_121 -to VGA_B[2]
set_location_assignment PIN_120 -to VGA_B[1]
set_location_assignment PIN_115 -to VGA_B[0]
set_location_assignment PIN_114 -to VGA_G[5]
set_location_assignment PIN_113 -to VGA_G[4]
set_location_assignment PIN_112 -to VGA_G[3]
set_location_assignment PIN_111 -to VGA_G[2]
set_location_assignment PIN_110 -to VGA_G[1]
set_location_assignment PIN_106 -to VGA_G[0]
set_location_assignment PIN_136 -to VGA_VS
set_location_assignment PIN_119 -to VGA_HS
set_location_assignment PIN_65 -to AUDIO_L
set_location_assignment PIN_80 -to AUDIO_R
set_location_assignment PIN_105 -to SPI_DO
set_location_assignment PIN_88 -to SPI_DI
set_location_assignment PIN_126 -to SPI_SCK
set_location_assignment PIN_127 -to SPI_SS2
set_location_assignment PIN_91 -to SPI_SS3
set_location_assignment PIN_13 -to CONF_DATA0
set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component"
# Classic Timing Assignments
# ==========================
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF
# Analysis & Synthesis Assignments
# ================================
set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name TOP_LEVEL_ENTITY Arkanoid_Mist
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name SAVE_DISK_SPACE OFF
# Fitter Assignments
# ==================
set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF
set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
set_global_assignment -name DEVICE EP3C25E144C8
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"
# Assembler Assignments
# =====================
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# Power Estimation Assignments
# ============================
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
# Advanced I/O Timing Assignments
# ===============================
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
# -----------------------
# start ENTITY(Centipede)
# start DESIGN_PARTITION(Top)
# ---------------------------
# Incremental Compilation Assignments
# ===================================
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(Centipede)
# ---------------------
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_global_assignment -name SYSTEMVERILOG_FILE rtl/Arkanoid_Mist.sv
set_global_assignment -name VHDL_FILE rtl/arkanoid.vhd
set_global_assignment -name VHDL_FILE rtl/arkanoid_view.vhd
set_global_assignment -name VHDL_FILE rtl/arkanoid_sound.vhd
set_global_assignment -name VHDL_FILE rtl/arkanoid_package.vhd
set_global_assignment -name VHDL_FILE rtl/arkanoid_levels_rom.vhd
set_global_assignment -name VHDL_FILE rtl/arkanoid_datapath.vhd
set_global_assignment -name VHDL_FILE rtl/arkanoid_controller.vhd
set_global_assignment -name VHDL_FILE rtl/vga_package.vhd
set_global_assignment -name VHDL_FILE rtl/sqrt.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
set_global_assignment -name VERILOG_FILE rtl/scandoubler.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv
set_global_assignment -name VERILOG_FILE rtl/mist_io.v
set_global_assignment -name VERILOG_FILE rtl/osd.v
set_global_assignment -name VHDL_FILE rtl/PLL.vhd
set_global_assignment -name VERILOG_FILE rtl/keyboard.v
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -0,0 +1,35 @@
# Arkanoid-VHDL
Arkanoid hardware implementation for FPGA, tested on Altera Cyclone II DE1 board, developed using Altera Quartus II Web Edition.
Video presentation: https://www.youtube.com/watch?v=pVajZEJieoY
##Project structure
* arkanoid-vhdl-master: main project files (source code)
* Arkanoid Level Editor: a nice wysiwyg level editor that lets you create your own levels,
providing functions for loading/saving .mif files. Remember to compile after editing arkanoid-vhdl-master/levels.mif
* Project report (ITALIAN only).pdf: project final report (italian only)
##Setup
1. Create new Quartus II project "arkanoid-vhdl-master"
2. Copy arkanoid-vhdl-master source files inside project
3. (Quartus II) Assignments -> Import Assignments -> File name: /PATH_TO/DE1.qsf -> Ok (DE1.qsf is located in "arkanoid-vhdl-master" folder)
3. Compile
4. Program device (after connecting DE1 board through USB port)
5. Connect a display through DE1 VGA port
6. Connect a PS/2 Keyboard to DE1 PS/2 Port
7. (optional) Connect a buzzer to DE1 GPIO_0(0) pin
8. Press spacebar
9. Enjoy :)
##Key bindings
* Move LEFT: "Y"
* Move RIGHT: "I"
* Start: spacebar
* Pause: "P"
* Reset: Altera DE1 Key(0) physical button
##Authors
Pietro Bassi
Marco Torsello

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,147 @@
//============================================================================
// Arcade: Arkanoid
//
// Port to MiST
// Copyright (C) 2018 Gehstock
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//============================================================================
module Arkanoid_Mist
(
output LED,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B,
output VGA_HS,
output VGA_VS,
output AUDIO_L,
output AUDIO_R,
input SPI_SCK,
output SPI_DO,
input SPI_DI,
input SPI_SS2,
input SPI_SS3,
input CONF_DATA0,
input CLOCK_27
);
`include "rtl\build_id.v"
localparam CONF_STR = {
"Arkanoid;;",
"O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
"T7,Reset;",
"V,v1.00.",`BUILD_DATE
};
wire [31:0] status;
wire [1:0] buttons;
wire [1:0] switches;
wire [9:0] kbjoy;
wire [7:0] joystick_0;
wire [7:0] joystick_1;
wire scandoubler_disable;
wire ypbpr;
wire ps2_kbd_clk, ps2_kbd_data;
assign LED = 1;
wire clk_50, clk_25, clk_6p25;
pll pll(
.inclk0(CLOCK_27),
.c0(clk_50),
.c1(clk_25),
.c3(clk_6p25)
);
arkanoid arkanoid(
.CLOCK(clk_50),
.CLOCKVGA(clk_25),
.RESET(~(status[0] | status[7] | buttons[1])),
.K_LEFT(kbjoy[6] | joystick_0[1] | joystick_1[1]),
.K_RIGHT(kbjoy[7] | joystick_0[0] | joystick_1[0]),
.K_PAUSE(kbjoy[3] | joystick_0[5] | joystick_1[5]),
.K_START(kbjoy[0] | joystick_0[4] | joystick_1[4]),
.VGA_R(r),
.VGA_G(g),
.VGA_B(b),
.VGA_HS(hs),
.VGA_VS(vs),
.audio(AUDIO_L)
);
assign AUDIO_R = AUDIO_L;
wire hs, vs;
wire [3:0] r, g, b;
video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(0)) video_mixer
(
.clk_sys(clk_25),
.ce_pix(clk_6p25),
.ce_pix_actual(clk_6p25),
.SPI_SCK(SPI_SCK),
.SPI_SS3(SPI_SS3),
.SPI_DI(SPI_DI),
.R({r,r[1:0]}),
.G({g,g[1:0]}),
.B({b,b[1:0]}),
.HSync(hs),
.VSync(vs),
.VGA_R(VGA_R),
.VGA_G(VGA_G),
.VGA_B(VGA_B),
.VGA_VS(VGA_VS),
.VGA_HS(VGA_HS),
.scandoubler_disable(1'b1),//scandoubler_disable),
.scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 2'b11, status[4:3] == 2'b10, status[4:3] == 2'b01}),
.hq2x(status[4:3]==1),
.ypbpr_full(1),
.line_start(0),
.mono(0)
);
mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io
(
.clk_sys (clk_25 ),
.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 (joystick_0 ),
.joystick_1 (joystick_1 ),
.status (status )
);
keyboard keyboard(
.clk(clk_25),
.reset(),
.ps2_kbd_clk(ps2_kbd_clk),
.ps2_kbd_data(ps2_kbd_data),
.joystick(kbjoy)
);
endmodule

View File

@@ -0,0 +1,446 @@
-- megafunction wizard: %ALTPLL%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altpll
-- ============================================================
-- File Name: PLL.vhd
-- Megafunction Name(s):
-- altpll
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version
-- ************************************************************
--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.all;
ENTITY PLL IS
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC
);
END PLL;
ARCHITECTURE SYN OF pll IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC ;
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC ;
SIGNAL sub_wire6 : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL sub_wire7_bv : BIT_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire7 : STD_LOGIC_VECTOR (0 DOWNTO 0);
COMPONENT altpll
GENERIC (
bandwidth_type : STRING;
clk0_divide_by : NATURAL;
clk0_duty_cycle : NATURAL;
clk0_multiply_by : NATURAL;
clk0_phase_shift : STRING;
clk1_divide_by : NATURAL;
clk1_duty_cycle : NATURAL;
clk1_multiply_by : NATURAL;
clk1_phase_shift : STRING;
clk2_divide_by : NATURAL;
clk2_duty_cycle : NATURAL;
clk2_multiply_by : NATURAL;
clk2_phase_shift : STRING;
clk3_divide_by : NATURAL;
clk3_duty_cycle : NATURAL;
clk3_multiply_by : NATURAL;
clk3_phase_shift : STRING;
compensate_clock : STRING;
inclk0_input_frequency : NATURAL;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
operation_mode : STRING;
pll_type : STRING;
port_activeclock : STRING;
port_areset : STRING;
port_clkbad0 : STRING;
port_clkbad1 : STRING;
port_clkloss : STRING;
port_clkswitch : STRING;
port_configupdate : STRING;
port_fbin : STRING;
port_inclk0 : STRING;
port_inclk1 : STRING;
port_locked : STRING;
port_pfdena : STRING;
port_phasecounterselect : STRING;
port_phasedone : STRING;
port_phasestep : STRING;
port_phaseupdown : STRING;
port_pllena : STRING;
port_scanaclr : STRING;
port_scanclk : STRING;
port_scanclkena : STRING;
port_scandata : STRING;
port_scandataout : STRING;
port_scandone : STRING;
port_scanread : STRING;
port_scanwrite : STRING;
port_clk0 : STRING;
port_clk1 : STRING;
port_clk2 : STRING;
port_clk3 : STRING;
port_clk4 : STRING;
port_clk5 : STRING;
port_clkena0 : STRING;
port_clkena1 : STRING;
port_clkena2 : STRING;
port_clkena3 : STRING;
port_clkena4 : STRING;
port_clkena5 : STRING;
port_extclk0 : STRING;
port_extclk1 : STRING;
port_extclk2 : STRING;
port_extclk3 : STRING;
width_clock : NATURAL
);
PORT (
clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0)
);
END COMPONENT;
BEGIN
sub_wire7_bv(0 DOWNTO 0) <= "0";
sub_wire7 <= To_stdlogicvector(sub_wire7_bv);
sub_wire4 <= sub_wire0(2);
sub_wire3 <= sub_wire0(0);
sub_wire2 <= sub_wire0(3);
sub_wire1 <= sub_wire0(1);
c1 <= sub_wire1;
c3 <= sub_wire2;
c0 <= sub_wire3;
c2 <= sub_wire4;
sub_wire5 <= inclk0;
sub_wire6 <= sub_wire7(0 DOWNTO 0) & sub_wire5;
altpll_component : altpll
GENERIC MAP (
bandwidth_type => "AUTO",
clk0_divide_by => 27,
clk0_duty_cycle => 50,
clk0_multiply_by => 50,
clk0_phase_shift => "0",
clk1_divide_by => 27,
clk1_duty_cycle => 50,
clk1_multiply_by => 25,
clk1_phase_shift => "0",
clk2_divide_by => 54,
clk2_duty_cycle => 50,
clk2_multiply_by => 25,
clk2_phase_shift => "0",
clk3_divide_by => 108,
clk3_duty_cycle => 50,
clk3_multiply_by => 25,
clk3_phase_shift => "0",
compensate_clock => "CLK0",
inclk0_input_frequency => 37037,
intended_device_family => "Cyclone III",
lpm_hint => "CBX_MODULE_PREFIX=PLL",
lpm_type => "altpll",
operation_mode => "NORMAL",
pll_type => "AUTO",
port_activeclock => "PORT_UNUSED",
port_areset => "PORT_UNUSED",
port_clkbad0 => "PORT_UNUSED",
port_clkbad1 => "PORT_UNUSED",
port_clkloss => "PORT_UNUSED",
port_clkswitch => "PORT_UNUSED",
port_configupdate => "PORT_UNUSED",
port_fbin => "PORT_UNUSED",
port_inclk0 => "PORT_USED",
port_inclk1 => "PORT_UNUSED",
port_locked => "PORT_UNUSED",
port_pfdena => "PORT_UNUSED",
port_phasecounterselect => "PORT_UNUSED",
port_phasedone => "PORT_UNUSED",
port_phasestep => "PORT_UNUSED",
port_phaseupdown => "PORT_UNUSED",
port_pllena => "PORT_UNUSED",
port_scanaclr => "PORT_UNUSED",
port_scanclk => "PORT_UNUSED",
port_scanclkena => "PORT_UNUSED",
port_scandata => "PORT_UNUSED",
port_scandataout => "PORT_UNUSED",
port_scandone => "PORT_UNUSED",
port_scanread => "PORT_UNUSED",
port_scanwrite => "PORT_UNUSED",
port_clk0 => "PORT_USED",
port_clk1 => "PORT_USED",
port_clk2 => "PORT_USED",
port_clk3 => "PORT_USED",
port_clk4 => "PORT_UNUSED",
port_clk5 => "PORT_UNUSED",
port_clkena0 => "PORT_UNUSED",
port_clkena1 => "PORT_UNUSED",
port_clkena2 => "PORT_UNUSED",
port_clkena3 => "PORT_UNUSED",
port_clkena4 => "PORT_UNUSED",
port_clkena5 => "PORT_UNUSED",
port_extclk0 => "PORT_UNUSED",
port_extclk1 => "PORT_UNUSED",
port_extclk2 => "PORT_UNUSED",
port_extclk3 => "PORT_UNUSED",
width_clock => 5
)
PORT MAP (
inclk => sub_wire6,
clk => sub_wire0
);
END SYN;
-- ============================================================
-- 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 "1"
-- 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 "27"
-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "54"
-- Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "108"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE3 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "50.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "25.000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "12.500000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "6.250000"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0"
-- 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: 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: MULT_FACTOR0 NUMERIC "50"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "25"
-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "25"
-- Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "25"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "50.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "25.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "12.50000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "6.25000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 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: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 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: STICKY_CLK2 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK3 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_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_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 "27"
-- 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: CLK2_DIVIDE_BY NUMERIC "54"
-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "25"
-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "108"
-- Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "25"
-- Retrieval info: CONSTANT: CLK3_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_UNUSED"
-- 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_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: WIDTH_CLOCK NUMERIC "5"
-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..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: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
-- 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: GEN_FILE: TYPE_NORMAL PLL.vhd 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.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf
-- Retrieval info: CBX_MODULE_PREFIX: ON

View File

@@ -0,0 +1,189 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use work.arkanoid_package.all;
entity arkanoid is
port
(
CLOCK : in std_logic;--50
CLOCKVGA : in std_logic;--25
RESET : in std_logic;
K_LEFT : in std_logic;
K_RIGHT : in std_logic;
K_PAUSE : in std_logic;
K_START : in std_logic;
VGA_R : out std_logic_vector(3 downto 0);
VGA_G : out std_logic_vector(3 downto 0);
VGA_B : out std_logic_vector(3 downto 0);
VGA_HS : out std_logic;
VGA_VS : out std_logic;
audio : out std_logic
);
end;
architecture RTL of arkanoid is
signal ballX : integer range -BALL_MAX_SPEED to GAME_WIDTH+BALL_MAX_SPEED := BALL_STARTING_POSX;
signal ballY : integer range -BALL_MAX_SPEED to GAME_HEIGHT+BALL_MAX_SPEED := BALL_STARTING_POSY;
signal powerUpX : natural range 0 to GAME_WIDTH;
signal powerUpY : natural range 0 to GAME_HEIGHT+100;
signal paddleX : integer range -PADDLE_SPEED_X to GAME_WIDTH+PADDLE_SPEED_X := PADDLE_STARTING_POSX;
signal paddleWidth : natural range PADDLE_STARTING_WIDTH to 2*PADDLE_STARTING_WIDTH := PADDLE_STARTING_WIDTH;
signal currentLevel : natural range 0 to LEVELS;
signal state : state_type;
signal gameTime : std_logic;
signal paddleMoveDir : integer range -1 to 1;
signal brickMatrix : brick_matrix_type(0 to BRICK_MAX_ROW-1, 0 to BRICK_MAX_COL-1);
signal resetSyncReg : std_logic;
signal RESET_N : std_logic;
signal bricksForNextLevel : unsigned(0 to 7);
signal levelComplete : std_logic;
signal lives : natural range 0 to MAX_LIVES;
signal lifeLost : std_logic;
signal levelLoaded : std_logic;
signal romAddr : std_logic_vector(10 downto 0);
signal romQ : std_logic_vector(3 downto 0);
signal powerUpType : powerup_type;
signal sound : sound_type;
signal squaredX : std_logic_vector(15 downto 0);
signal squaredY : std_logic_vector(15 downto 0);
signal rootX : std_logic_vector(7 downto 0);
signal rootY : std_logic_vector(7 downto 0);
signal clear : std_logic;
begin
datapath : entity work.arkanoid_datapath
port map
(
CLOCK => clock,
GAME_LOGIC_UPDATE => gameTime,
RESET_N => RESET_N,
PADDLE_MOVE_DIR => paddleMoveDir,
STATE => state,
BALL_X => ballX,
BALL_Y => ballY,
PADDLE_X => paddleX,
PADDLE_WIDTH => paddleWidth,
BRICK_MATRIX => brickMatrix,
LEVEL_COMPLETE => levelComplete,
LIVES => lives,
LIFE_LOST => lifeLost,
LEVEL_LOADED => levelLoaded,
ROM_ADDR => romAddr,
ROM_Q => romQ,
SQUARED_X => squaredX,
SQUARED_Y => squaredY,
ROOT_X => rootX,
ROOT_Y => rootY,
SQRT_CLEAR => clear,
POWERUP_X => powerUpX,
POWERUP_Y => powerUpY,
POWERUP => powerUpType,
SOUND => sound
);
controller : entity work.arkanoid_controller
port map
(
CLOCK => clock,
RESET_N => RESET_N,
BUTTON_LEFT => K_LEFT,
BUTTON_RIGHT => K_RIGHT,
BUTTON_PAUSE => K_PAUSE,
BUTTON_START => K_START,
PADDLE_MOVE_DIR => paddleMoveDir,
STATE => state,
LEVEL_COMPLETE => levelComplete,
LIVES => lives,
LIFE_LOST => lifeLost,
LEVEL_LOADED => levelLoaded
);
view : entity work.arkanoid_view
port map
(
CLOCK => clockVGA,
RESET_N => RESET_N,
VGA_R => VGA_R,
VGA_G => VGA_G,
VGA_B => VGA_B,
VGA_HS => VGA_HS,
VGA_VS => VGA_VS,
BALL_X => ballX/UNIT,
BALL_Y => ballY/UNIT,
PADDLE_X => paddleX/UNIT,
PADDLE_WIDTH => paddleWidth/UNIT,
BRICK_MATRIX => brickMatrix,
LIVES => lives,
STATE => state,
POWERUP_X => powerUpX/UNIT,
POWERUP_Y => powerUpY/UNIT,
POWERUP => powerUpType
);
arkanoid_levels_rom : entity work.arkanoid_levels_rom
port map
(
address => romAddr,
clock => clock,
q => romQ
);
sqrtX : entity work.sqrt
port map
(
CLOCK => clock,
CLEAR => clear,
DATA_IN => squaredX,
DATA_OUT => rootX
);
sqrtY : entity work.sqrt
port map
(
CLOCK => clock,
CLEAR => clear,
DATA_IN => squaredY,
DATA_OUT => rootY
);
arkanoid_sound : entity work.arkanoid_sound
port map
(
CLOCK => clock,
RESET_N => RESET_N,
SOUND_PIN => audio,
SOUND_CODE => sound
);
reset_sync : process(clock)
begin
if (rising_edge(clock)) then
resetSyncReg <= RESET;
RESET_N <= resetSyncReg;
end if;
end process;
game_time_generator : process(clock, RESET_N)
variable counter : integer range 0 to (GAME_LOGIC_UPDATE_RATE-1);
begin
if (RESET_N = '0') then
counter := 0;
gameTime <= '0';
elsif (rising_edge(clock)) then
if(counter = counter'high) then
counter := 0;
gameTime <= '1';
else
counter := counter+1;
gameTime <= '0';
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,145 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
library work;
use work.arkanoid_package.all;
entity arkanoid_controller is
port
(
CLOCK : in std_logic;
RESET_N : in std_logic;
BUTTON_LEFT : in std_logic;
BUTTON_RIGHT : in std_logic;
BUTTON_PAUSE : in std_logic;
BUTTON_START : in std_logic;
LEVEL_COMPLETE : in std_logic;
LEVEL_LOADED : in std_logic;
LIVES : in natural;
LIFE_LOST : in std_logic;
PADDLE_MOVE_DIR : out integer;
STATE : out state_type
);
end arkanoid_controller;
architecture RTL of arkanoid_controller is
constant DIR_LEFT : integer := -1;
constant DIR_RIGHT : integer := 1;
signal currState : state_type := S_INIT;
signal startRegister : std_logic:='0';
begin
StateSwitcher : process(CLOCK, RESET_N)
variable currentLevel : natural range 0 to LEVELS :=0;
begin
if (RESET_N='0') then
currState<=S_INIT;
elsif (rising_edge(CLOCK)) then
--in order to register the "key down" event only
startRegister<=BUTTON_START;
case currState is
--INIT
when S_INIT=>
currentLevel:=0;
currState <= S_CHANGELEVEL;
--PAUSED
when S_PAUSED=>
if (BUTTON_START = '1' and startRegister='0') then
currState <= S_PLAYING;
else
currState <= S_PAUSED;
end if;
--PLAYING
when S_PLAYING=>
if (BUTTON_PAUSE = '1') then
currState <= S_PAUSED;
elsif(LEVEL_COMPLETE='1') then
currentLevel:=currentLevel+1;
if(currentLevel/=currentLevel'high) then
currState <= S_CHANGELEVEL;
else
currState <= S_GAMEWON;
end if;
elsif(LIFE_LOST='1') then
if(LIVES>0) then
currState <= S_LIFELOST;
else
currState <= S_GAMELOST;
end if;
end if;
--CHANGELEVEL
when S_CHANGELEVEL=>
if(LEVEL_LOADED='1') then
currState <= S_PAUSED;
else
currState <= S_CHANGELEVEL;
end if;
--LIFELOST
when S_LIFELOST=>
currState <= S_PAUSED;
--GAMELOST
when S_GAMELOST=>
if (BUTTON_START='1' and startRegister='0') then
currState <= S_INIT;
else
currState <= S_GAMELOST;
end if;
--GAMEWON
when S_GAMEWON=>
if (BUTTON_START='1' and startRegister='0') then
currState <= S_INIT;
else
currState <= S_GAMEWON;
end if;
end case;
end if;
end process;
StateOutput : process(currState)
begin
case currState is
when S_INIT =>
STATE <= S_INIT;
when S_PAUSED =>
STATE <= S_PAUSED;
when S_PLAYING =>
STATE <= S_PLAYING;
when S_CHANGELEVEL =>
STATE <= S_CHANGELEVEL;
when S_LIFELOST =>
STATE <= S_LIFELOST;
when S_GAMELOST =>
STATE <= S_GAMELOST;
when S_GAMEWON =>
STATE <= S_GAMEWON;
end case;
end process;
InputProcess : process(CLOCK, RESET_N)
begin
if (rising_edge(CLOCK)) then
--process signals from arkanoid_keyboard and send PADDLE_MOVE_DIR to arkanoid_datapath
if (BUTTON_LEFT='1') then
PADDLE_MOVE_DIR<=DIR_LEFT;
elsif (BUTTON_RIGHT='1') then
PADDLE_MOVE_DIR<=DIR_RIGHT;
elsif (BUTTON_LEFT='0' and BUTTON_RIGHT='0') then
PADDLE_MOVE_DIR<=0;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,576 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
library work;
use work.arkanoid_package.all;
entity arkanoid_datapath is
port
(
CLOCK : in std_logic;
GAME_LOGIC_UPDATE : in std_logic;
RESET_N : in std_logic;
PADDLE_MOVE_DIR : in integer;
STATE : in state_type;
ROM_Q : in std_logic_vector(3 downto 0);
ROOT_X : in std_logic_vector (7 downto 0);
ROOT_Y : in std_logic_vector (7 downto 0);
LIFE_LOST : inout std_logic;
LEVEL_LOADED : inout std_logic;
ROM_ADDR : inout std_logic_vector(10 downto 0);
SQUARED_X : out std_logic_vector (15 downto 0);
SQUARED_Y : out std_logic_vector (15 downto 0);
SQRT_CLEAR : out std_logic;
POWERUP : out powerup_type;
SOUND : out sound_type;
LEVEL_COMPLETE : out std_logic;
BALL_X : out integer;
BALL_Y : out integer;
POWERUP_X : out integer;
POWERUP_Y : out integer;
PADDLE_X : out integer;
PADDLE_WIDTH : out integer;
LIVES : out natural;
BRICK_MATRIX : out brick_matrix_type(0 to BRICK_MAX_ROW-1, 0 to BRICK_MAX_COL-1)
);
end arkanoid_datapath;
architecture RTL of arkanoid_datapath is
--ball signals
signal ballX : integer range -BALL_MAX_SPEED to GAME_WIDTH+BALL_MAX_SPEED := BALL_STARTING_POSX;
signal ballY : integer range -BALL_MAX_SPEED to GAME_HEIGHT+BALL_MAX_SPEED := BALL_STARTING_POSY;
signal X : integer range ballX'low to ballX'high;
signal Y : integer range ballY'low to ballY'high;
signal ballTopX : integer range ballX'low to ballX'high;
signal ballBotX : integer range ballX'low to ballX'high;
signal ballLeftX : integer range ballX'low to ballX'high;
signal ballRightX : integer range ballX'low to ballX'high;
signal ballTopLeftX : integer range ballX'low to ballX'high;
signal ballTopRightX : integer range ballX'low to ballX'high;
signal ballBotLeftX : integer range ballX'low to ballX'high;
signal ballBotRightX : integer range ballX'low to ballX'high;
signal ballTopY : integer range ballX'low to ballX'high;
signal ballBotY : integer range ballX'low to ballX'high;
signal ballLeftY : integer range ballX'low to ballX'high;
signal ballRightY : integer range ballX'low to ballX'high;
signal ballTopLeftY : integer range ballX'low to ballX'high;
signal ballTopRightY : integer range ballX'low to ballX'high;
signal ballBotLeftY : integer range ballX'low to ballX'high;
signal ballBotRightY : integer range ballX'low to ballX'high;
signal ballAngleX : integer range -UNIT to UNIT:=0;
signal ballAngleY : integer range -UNIT to UNIT:=0;
signal signX : integer range -1 to 1;
signal signY : integer range -1 to 1;
signal squaredSpeed : natural range 0 to BALL_MAX_SPEED**2;
--paddle signals
signal paddleX : integer range -PADDLE_SPEED_X to GAME_WIDTH+PADDLE_SPEED_X := PADDLE_STARTING_POSX;
signal paddleWidth : natural range PADDLE_STARTING_WIDTH to 2*PADDLE_STARTING_WIDTH := PADDLE_STARTING_WIDTH;
signal nextPaddleX : integer range paddleX'low to paddleX'high;
shared variable paddleEnlarged : std_logic:='0';
--powerup signals
signal powerUpX : natural range 0 to GAME_WIDTH;
signal powerUpY : natural range 0 to GAME_HEIGHT+100;
signal powerUpFalling : std_logic:='0';
signal powerUpType : powerup_type;
signal powerUpCounter : unsigned(0 to 4);
signal powerUpCaught : powerup_type;
--current level signals
signal brickMatrix : brick_matrix_type(0 to BRICK_MAX_ROW-1, 0 to BRICK_MAX_COL-1);
shared variable i : natural range 0 to BRICK_MAX_ROW:=BRICK_MAX_ROW;
shared variable k : natural range 0 to BRICK_MAX_COL:=BRICK_MAX_COL;
signal romRdy : unsigned(3 downto 0):="0000";
signal romAddr : unsigned(10 downto 0);
signal bricksForNextLevel : natural range 0 to BRICK_MAX_ROW*BRICK_MAX_COL*UNIT:=1;
signal i_rom : natural range 0 to BRICK_MAX_ROW;
signal k_rom : natural range 0 to BRICK_MAX_COL;
shared variable brickHit : brickhit_type;
shared variable brickX : natural range 0 to BOUND_RIGHT;
shared variable brickY : natural range 0 to BOUND_BOTTOM;
signal brickCollisionCheckEnded : std_logic;
--game signals
signal gameLogicEnded : std_logic:='1';
signal currentLevel : natural range 0 to LEVELS-1;
signal livesLeft : natural range 0 to MAX_LIVES;
begin
LevelProcess : process(CLOCK, RESET_N, brickMatrix)
begin
if(rising_edge(CLOCK)) then
--INIT
if(STATE=S_INIT) then
currentLevel<=0;
romAddr<="00000000000";
romRdy<="0000";
LEVEL_LOADED<='0';
i_rom<=0;
k_rom<=0;
bricksForNextLevel<=0;
--CHANGELEVEL
elsif(STATE=S_CHANGELEVEL) then
LEVEL_COMPLETE<='0';
--load level
if(LEVEL_LOADED='0') then
ROM_ADDR<=std_logic_vector(romAddr(ROM_ADDR'range));
romAddr<=romAddr+"00000000001";
if(i_rom/=BRICK_MAX_ROW) then
brickMatrix(i_rom,k_rom) <= unsigned(ROM_Q);
if(unsigned(ROM_Q)>=B_WHITE and unsigned(ROM_Q)<=B_GREY5 and romRdy="0011") then
bricksForNextLevel<=bricksForNextLevel+1;
end if;
if(romRdy<"0011") then
romRdy<=romRdy+1;
else
if(k_rom/=BRICK_MAX_COL-1)then
k_rom<=k_rom+1;
else
k_rom<=0;
i_rom<=i_rom+1;
end if;
end if;
else
LEVEL_LOADED<='1';
end if;
--when level has been loaded
else
romRdy<="0000";
i_rom<=0;
k_rom<=0;
LEVEL_LOADED<='0';
LEVEL_COMPLETE<='0';
end if;
--PLAYING
elsif(STATE=S_PLAYING) then
--update brick matrix if a collision has happened
if((brickHit=B_BOUNCE or brickHit=B_DESTROYED) and brickCollisionCheckEnded='1') then
brickMatrix(i,k)<=brick_collision_result(brickMatrix(i,k));
if(brickMatrix(i,k)>=B_WHITE and brickMatrix(i,k)<=B_GREY1) then
bricksForNextLevel<=bricksForNextLevel-1;
end if;
end if;
--game logic update
if(GAME_LOGIC_UPDATE='1') then
--check if there are no bricks left
if(bricksForNextLevel=0) then
if(currentLevel=LEVELS-1) then
currentLevel<=0;
else
currentLevel<=currentLevel+1;
romAddr<=romAddr+"00000000100";
end if;
LEVEL_COMPLETE<='1';
end if;
end if;
end if;
end if; --clock if
BRICK_MATRIX<=brickMatrix;
end process;
BallProcess : process(CLOCK, RESET_N, ballX, ballY, livesLeft)
variable hitPoint : integer range -1 to 9;
begin
if(rising_edge(CLOCK)) then
--INIT
if(STATE=S_INIT) then
livesLeft<=STARTING_LIVES;
LIFE_LOST<='0';
--CHANGELEVEL
elsif(STATE=S_CHANGELEVEL) then
if(LEVEL_LOADED='1') then
ballX<=BALL_STARTING_POSX;
ballY<=BALL_STARTING_POSY;
ballAngleX<=0;
ballAngleY<=UNIT;
signX<=1;
signY<=1;
i:=BRICK_MAX_ROW;
k:=BRICK_MAX_COL;
end if;
--PAUSED
elsif(STATE=S_PAUSED) then
LIFE_LOST<='0';
--LIFELOST
elsif(STATE=S_LIFELOST) then
ballX<=BALL_STARTING_POSX;
ballY<=BALL_STARTING_POSY;
ballAngleX<=0;
ballAngleY<=UNIT;
signX<=1;
signY<=1;
--PLAYING
elsif(STATE=S_PLAYING) then
SOUND<=PLAY_NULL;
brickCollisionCheckEnded<='0';
--after game logic phase, send squares of x and y speed components to sqrt entities
if(gameLogicEnded='1') then
SQRT_CLEAR<='1';
SQUARED_X<=std_logic_vector(to_unsigned(squaredSpeed*ballAngleX, SQUARED_X'length));
SQUARED_Y<=std_logic_vector(to_unsigned(squaredSpeed*ballAngleY, SQUARED_Y'length));
gameLogicEnded<='0';
--reset i and k values so the bounce check can start
i:=0;
k:=0;
else
SQRT_CLEAR<='0';
end if;
--store in X and Y the prediction of ball position, based on square roots of x and y speed components
X<=ballX+to_integer(unsigned(ROOT_X))*signX;
Y<=ballY+to_integer(unsigned(ROOT_Y))*signY;
ballTopX <= X+BALL_SIZE/2;
ballTopY <= Y;
ballBotX <= X+BALL_SIZE/2;
ballBotY <= Y+BALL_SIZE-1*UNIT;
ballLeftX <= X;
ballLeftY <= Y+BALL_SIZE/2;
ballRightX <= X+BALL_SIZE-1*UNIT;
ballRightY <= Y+BALL_SIZE/2;
ballTopLeftX <= X+2*UNIT;
ballTopLeftY <= Y+2*UNIT;
ballTopRightX <= X+BALL_SIZE-3*UNIT;
ballTopRightY <= Y+2*UNIT;
ballBotLeftX <= X+2*UNIT;
ballBotLeftY <= Y+BALL_SIZE-3*UNIT;
ballBotRightX <= X+BALL_SIZE-3*UNIT;
ballBotRightY <= Y+BALL_SIZE-3*UNIT;
--brick matrix bounce
if(i/=BRICK_MAX_ROW and brickHit=B_NULL) then
brickX:=k*BRICK_WIDTH+BRICK_MATRIX_X;
brickY:=i*BRICK_HEIGHT+BRICK_MATRIX_Y;
--if there is a collision with a non-empty brick
if(brickMatrix(i,k)>B_EMPTY) then
--ball hits the LEFT side of the brick
if(is_colliding(ballRightX,ballRightY,brickX,brickY)) then
signX<=-1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
ballX<=2*brickX-2*BALL_SIZE-X;
--ball hits the RIGHT side of the brick
elsif(is_colliding(ballLeftX,ballLeftY,brickX,brickY)) then
signX<=1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
ballX<=2*brickX+2*BRICK_WIDTH-X;
--ball hits the TOP side of the brick
elsif(is_colliding(ballBotX,ballBotY,brickX,brickY)) then
signY<=-1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
ballY<=2*brickY-2*BALL_SIZE-Y;
--ball hits the BOT side of the brick
elsif(is_colliding(ballTopX,ballTopY,brickX,brickY)) then
signY<=1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
ballY<=2*brickY+2*BRICK_HEIGHT-Y;
--ball hits the BOTTOM-LEFT edge of the brick
elsif(is_colliding(ballTopRightX,ballTopRightY,brickX,brickY)) then
signX<=-1;
signY<=1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
--ball hits the BOTTOM-RIGHT edge of the brick
elsif(is_colliding(ballTopLeftX,ballTopLeftY,brickX,brickY)) then
signX<=1;
signY<=1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
--ball hits the TOP-LEFT edge of the brick
elsif(is_colliding(ballBotRightX,ballBotRightY,brickX,brickY)) then
signX<=-1;
signY<=-1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
--ball hits the TOP-RIGHT edge of the brick
elsif(is_colliding(ballBotLeftX,ballBotLeftY,brickX,brickY)) then
signX<=1;
signY<=-1;
if(brick_collision_result(brickMatrix(i,k))=B_EMPTY) then
brickHit:=B_DESTROYED;
else
brickHit:=B_BOUNCE;
end if;
end if;
end if;
if(brickHit=B_NULL) then
k:=k+1;
if(k=BRICK_MAX_COL) then
k:=0;
i:=i+1;
end if;
else
brickCollisionCheckEnded<='1';
SOUND<=PLAY_BRICK;
end if;
end if;
--game logic update (and playing)
if(GAME_LOGIC_UPDATE='1') then
gameLogicEnded<='1';
brickHit:=B_NULL;
--right bound bounce
if (ballRightX>BOUND_RIGHT) then
ballX<=2*BOUND_RIGHT-2*BALL_SIZE-X;
signX<=-1;
SOUND<=PLAY_BOUND;
--left bound bounce
elsif (ballLeftX<=BOUND_LEFT) then
ballX<=2*BOUND_LEFT-X;
signX<=1;
SOUND<=PLAY_BOUND;
--top bound bounce
elsif (ballTopY<BOUND_TOP) then
ballY<=2*BOUND_TOP-Y;
signY<=1;
SOUND<=PLAY_BOUND;
--ball under bottom bound
elsif (ballTopY>BOUND_BOTTOM) then
livesLeft<=livesLeft-1;
LIFE_LOST<='1';
--paddle bounce
elsif (ballBotY>=PADDLE_STARTING_POSY and ballBotY<PADDLE_STARTING_POSY+PADDLE_HEIGHT and ballRightX>=paddleX and ballLeftX<=paddleX+paddleWidth) then
if(ballBotX>=paddleX+PADDLE_SIDE_SIZE and ballBotX<=paddleX+paddleWidth-PADDLE_SIDE_SIZE) then
if(paddleEnlarged='0') then
hitPoint:=((ballBotX)-(paddleX+PADDLE_SIDE_SIZE))/(10*UNIT); --total sections: 104-24=80/10=8
else
hitPoint:=((ballBotX)-(paddleX+PADDLE_SIDE_SIZE))/(30*UNIT/2);
end if;
case hitPoint is
when 0 => ballAngleX<=6; ballAngleY<=10; signX<=-1; signY<=-1;
when 1 => ballAngleX<=4; ballAngleY<=12; signX<=-1; signY<=-1;
when 2 => ballAngleX<=2; ballAngleY<=14; signX<=-1; signY<=-1;
when 3 => ballAngleX<=1; ballAngleY<=15; signX<=-1; signY<=-1;
when 4 => ballAngleX<=1; ballAngleY<=15; signX<=1; signY<=-1;
when 5 => ballAngleX<=2; ballAngleY<=14; signX<=1; signY<=-1;
when 6 => ballAngleX<=4; ballAngleY<=12; signX<=1; signY<=-1;
when 7 => ballAngleX<=6; ballAngleY<=10; signX<=1; signY<=-1;
when others => ballAngleX<=6; ballAngleY<=10; signX<=1; signY<=-1;
end case;
ballY<=(PADDLE_STARTING_POSY-BALL_SIZE)-(Y+BALL_SIZE-PADDLE_STARTING_POSY);
else
--left side bounce
if(ballBotX<paddleX+PADDLE_SIDE_SIZE) then
if(ballRightY>=PADDLE_STARTING_POSY) then
ballAngleX<=10; ballAngleY<=6; signX<=-1; signY<=-1;
ballX<=(paddleX-BALL_SIZE)-(X+BALL_SIZE-paddleX)+PADDLE_SPEED_X*PADDLE_MOVE_DIR-2;
else
ballAngleX<=8; ballAngleY<=8; signX<=-1; signY<=-1;
ballY<=(PADDLE_STARTING_POSY-BALL_SIZE)-(Y+BALL_SIZE-PADDLE_STARTING_POSY);
end if;
--right side bounce
else
if(ballLeftY>=PADDLE_STARTING_POSY) then
ballAngleX<=10; ballAngleY<=6; signX<=1; signY<=-1;
ballX<=paddleX+paddleWidth+(paddleX+paddleWidth-X)+PADDLE_SPEED_X*PADDLE_MOVE_DIR+2;
else
ballAngleX<=8; ballAngleY<=8; signX<=1; signY<=-1;
ballY<=(PADDLE_STARTING_POSY-BALL_SIZE)-(Y+BALL_SIZE-PADDLE_STARTING_POSY);
end if;
end if;
end if; --paddle middle if
SOUND<=PLAY_PADDLE;
else
ballX<=X;
ballY<=Y;
end if; --bounce if
--powerup: death
if(powerUpCaught=P_DEATH) then
livesLeft<=livesLeft-1;
LIFE_LOST<='1';
--powerup: life
elsif(powerUpCaught=P_LIFE and livesLeft<MAX_LIVES) then
livesLeft<=livesLeft+1;
end if;
end if; --game logic if
end if; --playing if
end if; --clock if
BALL_X <= ballX;
BALL_Y <= ballY;
LIVES<=livesLeft;
end process;
PaddleProcess : process(CLOCK, RESET_N, paddleX, paddleWidth)
begin
if (rising_edge(CLOCK)) then
--INIT, CHANGELEVEL, LIFELOST
if(STATE=S_INIT or STATE=S_CHANGELEVEL or STATE=S_LIFELOST) then
paddleX<=PADDLE_STARTING_POSX;
paddleWidth<=PADDLE_STARTING_WIDTH;
paddleEnlarged:='0';
--PLAYING
elsif(STATE=S_PLAYING) then
nextPaddleX<=paddleX+PADDLE_SPEED_X*PADDLE_MOVE_DIR;
--game logic update
if(GAME_LOGIC_UPDATE='1') then
--paddle movement
if (nextPaddleX<BOUND_LEFT) then
paddleX<=BOUND_LEFT;
elsif (nextPaddleX+paddleWidth>BOUND_RIGHT) then
paddleX<=BOUND_RIGHT-paddleWidth;
else
paddleX<=nextPaddleX;
end if;
--powerup: enlarge
if(powerUpCaught=P_ENLARGE) then
paddleEnlarged:='1';
paddleWidth<=(3*(PADDLE_STARTING_WIDTH-2*PADDLE_SIDE_SIZE))/2+2*PADDLE_SIDE_SIZE;
elsif(powerUpCaught=P_LIFE) then
paddleEnlarged:='0';
paddleWidth<=PADDLE_STARTING_WIDTH;
end if;
end if;
end if;
end if;
PADDLE_X <= paddleX;
PADDLE_WIDTH <= paddleWidth;
end process;
PowerupProcess : process(CLOCK, RESET_N, powerUpX, powerUpY, powerUpType)
begin
if (rising_edge(CLOCK)) then
powerUpCounter<=powerUpCounter+1;
--INIT, CHANGELEVEL, LIFELOST
if(STATE=S_INIT or STATE=S_CHANGELEVEL or STATE=S_LIFELOST) then
powerUpType<=P_NULL;
powerUpY<=POWERUP_OFF_Y;
powerUpCaught<=P_NULL;
--PLAYING
elsif(STATE=S_PLAYING) then
--game logic update
if(GAME_LOGIC_UPDATE='1') then
powerUpCaught<=P_NULL;
--if a brick has just been hit and the powerup is not active
if(brickHit=B_DESTROYED and powerUpY>=POWERUP_OFF_Y) then
powerUpX<=brickX+4*UNIT;
powerUpY<=brickY+3*UNIT;
case powerUpCounter is
when "00000"
=> powerUpType<=P_LIFE;
when "00001"
=> powerUpType<=P_SLOW;
when "00010"
=> powerUpType<=P_ENLARGE;
when "00011"|"10011"
=> powerUpType<=P_DEATH;
when "11000"|"11100"
=> powerUpType<=P_FAST;
when others => powerUpType<=P_NULL;
end case;
end if;
--if the powerup is active
if(powerUpY<POWERUP_OFF_Y) then
powerUpY<=powerUpY+POWERUP_SPEED_Y;
--if caught by paddle
if(powerUpX>=paddleX-POWERUP_WIDTH and powerUpX<paddleX+paddleWidth and powerUpY+POWERUP_HEIGHT/2>=PADDLE_STARTING_POSY and powerUpY+POWERUP_HEIGHT/2<PADDLE_STARTING_POSY+PADDLE_HEIGHT) then
powerUpCaught<=powerUpType;
powerUpY<=POWERUP_OFF_Y;
powerUpType<=P_NULL;
end if;
end if;
end if;
end if;
end if;
POWERUP_X<=powerUpX;
POWERUP_Y<=powerUpY;
POWERUP<=powerUpType;
end process;
SpeedProcess : process(CLOCK, RESET_N)
variable counter : integer range 0 to (BALL_SPEEDUP_RATE-1);
begin
if (RESET_N = '0') then
counter := 0;
elsif (rising_edge(CLOCK)) then
--INIT, CHANGELEVEL, LIFELOST
if(STATE=S_INIT or STATE=S_CHANGELEVEL or LIFE_LOST='1') then
squaredSpeed <= (BALL_STARTING_SPEED**2)/UNIT;
--PLAYING
elsif(STATE=S_PLAYING and squaredSpeed<(BALL_MAX_SPEED**2)/UNIT) then
if(counter = counter'high) then
counter := 0;
squaredSpeed <= squaredSpeed+1;
else
counter := counter+1;
squaredSpeed <= squaredSpeed;
end if;
--game logic update
if(GAME_LOGIC_UPDATE='1') then
--powerup: slow
if(powerUpCaught=P_SLOW) then
if(squaredSpeed-POWERUP_SPEED_MOD<(BALL_STARTING_SPEED**2)/UNIT) then
squaredSpeed<=(BALL_STARTING_SPEED**2)/UNIT;
else
squaredSpeed<=squaredSpeed-POWERUP_SPEED_MOD;
end if;
--powerup: fast
elsif(powerUpCaught=P_FAST) then
if(squaredSpeed+POWERUP_SPEED_MOD>(BALL_MAX_SPEED**2)/UNIT) then
squaredSpeed<=(BALL_MAX_SPEED**2)/UNIT;
else
squaredSpeed<=squaredSpeed+POWERUP_SPEED_MOD;
end if;
end if;
end if;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,169 @@
-- megafunction wizard: %ROM: 1-PORT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- ============================================================
-- File Name: arkanoid_levels_rom.vhd
-- Megafunction Name(s):
-- altsyncram
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version
-- ************************************************************
--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.all;
ENTITY arkanoid_levels_rom IS
PORT
(
address : IN STD_LOGIC_VECTOR (10 DOWNTO 0);
clock : IN STD_LOGIC := '1';
q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END arkanoid_levels_rom;
ARCHITECTURE SYN OF arkanoid_levels_rom IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
address_aclr_a : STRING;
clock_enable_input_a : STRING;
clock_enable_output_a : STRING;
init_file : STRING;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
numwords_a : NATURAL;
operation_mode : STRING;
outdata_aclr_a : STRING;
outdata_reg_a : STRING;
widthad_a : NATURAL;
width_a : NATURAL;
width_byteena_a : NATURAL
);
PORT (
address_a : IN STD_LOGIC_VECTOR (10 DOWNTO 0);
clock0 : IN STD_LOGIC ;
q_a : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(3 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
address_aclr_a => "NONE",
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => "./roms/levels.mif",
intended_device_family => "Cyclone III",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 2048,
operation_mode => "ROM",
outdata_aclr_a => "NONE",
outdata_reg_a => "CLOCK0",
widthad_a => 11,
width_a => 4,
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 "./roms/levels.mif"
-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "2048"
-- 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 "11"
-- Retrieval info: PRIVATE: WidthData NUMERIC "4"
-- 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 "./roms/levels.mif"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "2048"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "4"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]"
-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
-- Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL "q[3..0]"
-- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0
-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
-- Retrieval info: CONNECT: q 0 0 4 0 @q_a 0 0 4 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL arkanoid_levels_rom.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL arkanoid_levels_rom.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL arkanoid_levels_rom.cmp FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL arkanoid_levels_rom.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL arkanoid_levels_rom_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,115 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
package arkanoid_package is
--CONSTANTS
--game
constant UNIT : positive := 16;
constant GAME_LOGIC_UPDATE_RATE : positive := 416667;
constant GAME_WIDTH : natural := 640*UNIT;
constant GAME_HEIGHT : natural := 480*UNIT;
constant LEVELS : positive := 13;
constant STARTING_LIVES : positive := 3;
constant MAX_LIVES : positive := 4;
--bounds
constant BOUND_TOP_THICKNESS : natural := 50*UNIT;
constant BOUND_LAT_THICKNESS : natural := 20*UNIT;
constant BOUND_TOP : natural := BOUND_TOP_THICKNESS;
constant BOUND_LEFT : natural := BOUND_LAT_THICKNESS;
constant BOUND_RIGHT : natural := GAME_WIDTH-BOUND_LAT_THICKNESS;
constant BOUND_BOTTOM : natural := GAME_HEIGHT;
--ball
constant BALL_SIZE : natural := 13*UNIT;
constant BALL_STARTING_POSX : natural := GAME_WIDTH/2-BALL_SIZE;
constant BALL_STARTING_POSY : natural := 340*UNIT;
constant BALL_STARTING_SPEED : integer := 13*UNIT/4;
constant BALL_MAX_SPEED : integer := 5*UNIT;
constant BALL_SPEEDUP_RATE : integer := 15000000;
--paddle
constant PADDLE_HEIGHT : natural := 18*UNIT;
constant PADDLE_STARTING_WIDTH : natural := 104*UNIT;
constant PADDLE_STARTING_POSX : natural := GAME_WIDTH/2-PADDLE_STARTING_WIDTH/2;
constant PADDLE_STARTING_POSY : natural := GAME_HEIGHT-PADDLE_HEIGHT-16*UNIT;
constant PADDLE_SPEED_X : natural := 5*UNIT;
constant PADDLE_SIDE_SIZE : natural := 12*UNIT;
--brick
constant BRICK_WIDTH : natural := 40*UNIT;
constant BRICK_HEIGHT : natural := 20*UNIT;
constant BRICK_MATRIX_X : natural := BOUND_LEFT;
constant BRICK_MATRIX_Y : natural := BOUND_TOP+BRICK_HEIGHT*3;
constant BRICK_MAX_ROW : natural := 10;
constant BRICK_MAX_COL : natural := 15;
constant BRICK_TOTAL : natural := BRICK_MAX_ROW*BRICK_MAX_COL;
--powerup
constant POWERUP_WIDTH : natural := 32*UNIT;
constant POWERUP_HEIGHT : natural := 14*UNIT;
constant POWERUP_SPEED_Y : natural := 5*UNIT/2;
constant POWERUP_OFF_Y : natural := GAME_HEIGHT;
constant POWERUP_SPEED_MOD : natural := 4*UNIT;
--types definition
type state_type is (S_INIT, S_PAUSED, S_PLAYING, S_CHANGELEVEL, S_LIFELOST, S_GAMELOST, S_GAMEWON);
type powerup_type is (P_NULL, P_LIFE, P_SLOW, P_FAST, P_ENLARGE, P_DEATH);
type brickhit_type is (B_NULL, B_BOUNCE, B_DESTROYED);
type sound_type is (PLAY_NULL, PLAY_PADDLE, PLAY_BRICK, PLAY_BOUND);
subtype brick_type is unsigned(0 to 3);
type brick_matrix_type is array(natural range <>, natural range <>) of brick_type;
--bricks constants
constant B_EMPTY : brick_type := X"0";
constant B_WHITE : brick_type := X"1";
constant B_ORANGE : brick_type := X"2";
constant B_CYAN : brick_type := X"3";
constant B_GREEN : brick_type := X"4";
constant B_RED : brick_type := X"5";
constant B_BLUE : brick_type := X"6";
constant B_PINK : brick_type := X"7";
constant B_PURPLE : brick_type := X"8";
constant B_YELLOW : brick_type := X"9";
constant B_GREY1 : brick_type := X"A";
constant B_GREY2 : brick_type := X"B";
constant B_GREY3 : brick_type := X"C";
constant B_GREY4 : brick_type := X"D";
constant B_GREY5 : brick_type := X"E";
constant B_GOLD : brick_type := X"F";
--FUNCTIONS
function brick_collision_result ( brick : brick_type ) return brick_type;
function is_colliding ( pointX : integer; pointY : integer; brickX : integer; brickY : integer ) return boolean;
end package;
package body arkanoid_package is
function brick_collision_result ( brick : brick_type ) return brick_type is
begin
if (brick<=B_GREY1) then
return B_EMPTY;
elsif (brick>=B_GREY2 and brick<=B_GREY5) then
return brick-1;
else
return brick;
end if;
end brick_collision_result;
function is_colliding ( pointX : integer; pointY : integer; brickX : integer; brickY : integer ) return boolean is
begin
if (pointX>=brickX and pointX<brickX+BRICK_WIDTH and pointY>=brickY and pointY<brickY+BRICK_HEIGHT) then
return true;
else
return false;
end if;
end is_colliding;
end arkanoid_package;

View File

@@ -0,0 +1,99 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.ALL;
library work;
use work.arkanoid_package.all;
entity arkanoid_sound is
port
(
CLOCK : in std_logic;
RESET_N : in std_logic;
SOUND_CODE : in sound_type;
SOUND_PIN : out std_logic
);
end arkanoid_sound;
architecture RTL of arkanoid_sound is
constant CLOCK_FREQUENCY : integer := 50000000;
constant SOUND_PADDLE_FREQUENCY : integer := 494; -- Si4 (B4)
constant SOUND_BRICK_FREQUENCY : integer := 740; -- Fa#5 (F#5)
constant SOUND_BOUND_FREQUENCY : integer := 247; -- Si3 (B3)
constant CLOCK_DIVIDER_PADDLE : integer := CLOCK_FREQUENCY / SOUND_PADDLE_FREQUENCY /2 - 1;
constant CLOCK_DIVIDER_BRICK : integer := CLOCK_FREQUENCY / SOUND_BRICK_FREQUENCY /2 - 1;
constant CLOCK_DIVIDER_BOUND : integer := CLOCK_FREQUENCY / SOUND_BOUND_FREQUENCY /2 - 1;
constant COUNTER_SIZE : integer := 32;
constant SOUND_DURATION : integer := CLOCK_FREQUENCY/12;
signal soundPaddle :std_logic;
signal soundBrick :std_logic;
signal soundBound :std_logic;
signal counterSoundPaddle : std_logic_vector (COUNTER_SIZE - 1 downto 0);
signal counterSoundBrick : std_logic_vector (COUNTER_SIZE - 1 downto 0);
signal counterSoundBound : std_logic_vector (COUNTER_SIZE - 1 downto 0);
signal lengthCounter : std_logic_vector (COUNTER_SIZE - 1 downto 0);
begin
SoundProcess: process(CLOCK)
begin
if( rising_edge(CLOCK) )then
if(counterSoundPaddle = 0) then
counterSoundPaddle <= std_logic_vector(to_unsigned(CLOCK_DIVIDER_PADDLE,COUNTER_SIZE));
soundPaddle <= not soundPaddle;
else
counterSoundPaddle <= counterSoundPaddle - 1 ;
end if;
if(counterSoundBrick = 0) then
counterSoundBrick <= std_logic_vector(to_unsigned(CLOCK_DIVIDER_BRICK,COUNTER_SIZE));
soundBrick <= not soundBrick;
else
counterSoundBrick <= counterSoundBrick - 1 ;
end if;
if(counterSoundBound = 0) then
counterSoundBound <= std_logic_vector(to_unsigned(CLOCK_DIVIDER_BOUND,COUNTER_SIZE));
soundBound <= not soundBound;
else
counterSoundBound <= counterSoundBound - 1 ;
end if;
end if;
end process;
SoundCoordinator: process(CLOCK,RESET_N,SOUND_CODE)
variable sound :sound_type := PLAY_NULL;
begin
if( rising_edge(CLOCK) )then
if( RESET_N = '0' ) then
lengthCounter <= std_logic_vector(to_unsigned(SOUND_DURATION,COUNTER_SIZE));
SOUND_PIN<= '0';
sound:=PLAY_NULL;
else
if(SOUND_CODE/=PLAY_NULL) then
lengthCounter <= std_logic_vector(to_unsigned(SOUND_DURATION,COUNTER_SIZE));
sound := SOUND_CODE;
else
lengthCounter <= lengthCounter - 1;
end if;
if(lengthCounter > 0) then
case sound is
when PLAY_PADDLE => SOUND_PIN<= soundPaddle;
when PLAY_BRICK => SOUND_PIN<= soundBrick;
when PLAY_BOUND => SOUND_PIN<= soundBound;
when others => SOUND_PIN<= '0';
end case;
else
SOUND_PIN<= '0';
sound:=PLAY_NULL;
end if;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,433 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.arkanoid_package.all;
use work.vga_package.all;
entity arkanoid_view is
port
(
CLOCK : in std_logic;
RESET_N : in std_logic;
BALL_X : in integer;
BALL_Y : in integer;
PADDLE_X : in integer;
PADDLE_WIDTH : in integer;
BRICK_MATRIX : in brick_matrix_type(0 to BRICK_MAX_ROW-1, 0 to BRICK_MAX_COL-1);
LIVES : in natural;
STATE : in state_type;
POWERUP_X : in integer;
POWERUP_Y : in integer;
POWERUP : in powerup_type;
VGA_HS : out std_logic;
VGA_VS : out std_logic;
VGA_R : out std_logic_vector(3 downto 0);
VGA_G : out std_logic_vector(3 downto 0);
VGA_B : out std_logic_vector(3 downto 0)
);
end;
architecture RTL of arkanoid_view is
type light_state_type is (LS_DARKER_UP, LS_DARK_UP, LS_LIGHT_DN, LS_DARK_DN);
signal lightState : light_state_type;
signal backgroundFlagX : std_logic :='0';
signal backgroundFlagY : std_logic :='0';
signal changeLight : std_logic:='0';
signal lightColor : color_type:=COLOR_LIGHTDARKER;
signal heartColor : color_type:=COLOR_HEARTDARK;
begin
DrawProcess : process(CLOCK,RESET_N)
variable old_x : integer range 0 to TOTAL_W:=0;
variable old_y : integer range 0 to TOTAL_H:=0;
variable x : integer range 0 to VISIBLE_WIDTH:=0;
variable y : integer range 0 to VISIBLE_HEIGHT:=0;
variable brickX : integer;
variable brickY : integer;
variable brickColor : color_type;
alias R_BRICK is brickColor(0 to 3);
alias G_BRICK is brickColor(4 to 7);
alias B_BRICK is brickColor(8 to 11);
variable powerupColor : powerup_color_type;
alias R_POWERUP_LIGHT is powerupColor(0 to 3);
alias G_POWERUP_LIGHT is powerupColor(4 to 7);
alias B_POWERUP_LIGHT is powerupColor(8 to 11);
alias R_POWERUP_DARK is powerupColor(12 to 15);
alias G_POWERUP_DARK is powerupColor(16 to 19);
alias B_POWERUP_DARK is powerupColor(20 to 23);
begin
if(RESET_N='0') then
old_x:=0;
old_y:=0;
x:=0;
y:=0;
VGA_HS<='0';
VGA_VS<='0';
VGA_R <= X"0";
VGA_G <= X"0";
VGA_B <= X"0";
backgroundFlagX<='0';
backgroundFlagY<='0';
elsif rising_edge(CLOCK) then
if(changeLight = '1') then
case lightState is
when LS_DARKER_UP=>
lightState<=LS_DARK_UP;
when LS_DARK_UP=>
lightState<=LS_LIGHT_DN;
when LS_LIGHT_DN=>
lightState<=LS_DARK_DN;
when LS_DARK_DN=>
lightState<=LS_DARKER_UP;
end case;
end if;
--Vertical sync
if (old_y<VERTICAL_SYNC_PULSE) then
VGA_VS <='0';
else
VGA_VS <='1';
end if;
--Horizontal sync
if (old_x<HORIZONTAL_SYNC_PULSE) then
VGA_HS <='0';
else
VGA_HS <='1';
end if;
--inside the visible window
if(old_x>=WINDOW_HORIZONTAL_START and old_x<WINDOW_HORIZONTAL_END and old_y>=WINDOW_VERTICAL_START and old_y<WINDOW_VERTICAL_END) then
x:=old_x-WINDOW_HORIZONTAL_START;
y:=old_y-WINDOW_VERTICAL_START;
--draw background
if(x>=0 and x<VISIBLE_WIDTH) then
if(x mod BKG_RECT_WIDTH = 0) then
backgroundFlagX<=NOT backgroundFlagX;
end if;
if(x=0) then
backgroundFlagX<='0';
end if;
if(y mod BKG_RECT_HEIGHT = 0 and x=0) then
backgroundFlagY<=NOT backgroundFlagY;
end if;
if(y=0) then
backgroundFlagY<='0';
end if;
if(backgroundFlagX=backgroundFlagY) then
VGA_R <= COLOR_BKGBLUE(0 to 3);
VGA_G <= COLOR_BKGBLUE(4 to 7);
VGA_B <= COLOR_BKGBLUE(8 to 11);
if(STATE=S_GAMELOST) then
VGA_R <= COLOR_BKGRED(0 to 3);
VGA_G <= COLOR_BKGRED(4 to 7);
VGA_B <= COLOR_BKGRED(8 to 11);
elsif(STATE=S_GAMEWON) then
VGA_R <= COLOR_BKGGREEN(0 to 3);
VGA_G <= COLOR_BKGGREEN(4 to 7);
VGA_B <= COLOR_BKGGREEN(8 to 11);
end if;
else
VGA_R <= COLOR_BKGDARKBLUE(0 to 3);
VGA_G <= COLOR_BKGDARKBLUE(4 to 7);
VGA_B <= COLOR_BKGDARKBLUE(8 to 11);
if(STATE=S_GAMELOST) then
VGA_R <= COLOR_BKGDARKRED(0 to 3);
VGA_G <= COLOR_BKGDARKRED(4 to 7);
VGA_B <= COLOR_BKGDARKRED(8 to 11);
elsif(STATE=S_GAMEWON) then
VGA_R <= COLOR_BKGDARKGREEN(0 to 3);
VGA_G <= COLOR_BKGDARKGREEN(4 to 7);
VGA_B <= COLOR_BKGDARKGREEN(8 to 11);
end if;
end if;
end if;
--end draw background
--draw bounds
if(x<BOUND_LEFT/UNIT or x>=BOUND_RIGHT/UNIT or y<BOUND_TOP/UNIT) then
VGA_R <= X"3";
VGA_G <= X"3";
VGA_B <= X"3";
if(x>=BOUND_LEFT/UNIT-2 and x<BOUND_RIGHT/UNIT+2 and y>=BOUND_TOP/UNIT-2) then
VGA_R <= X"0";
VGA_G <= X"0";
VGA_B <= X"0";
end if;
end if;
--end draw bounds
--draw lives
if(y<=LIVES_Y+24) then
for i in 0 to MAX_LIVES-1 loop
if(i+1<=LIVES) then
if
(
(x>=LIVES_X+i*32+4 and x<LIVES_X+i*32+10 and y>=LIVES_Y+0 and y<LIVES_Y+16) or
(x>=LIVES_X+i*32+16 and x<LIVES_X+i*32+22 and y>=LIVES_Y+0 and y<LIVES_Y+16) or
(x>=LIVES_X+i*32+2 and x<LIVES_X+i*32+12 and y>=LIVES_Y+2 and y<LIVES_Y+14) or
(x>=LIVES_X+i*32+14 and x<LIVES_X+i*32+24 and y>=LIVES_Y+2 and y<LIVES_Y+14) or
(x>=LIVES_X+i*32+0 and x<LIVES_X+i*32+26 and y>=LIVES_Y+4 and y<LIVES_Y+12) or
(x>=LIVES_X+i*32+2 and x<LIVES_X+i*32+24 and y>=LIVES_Y+12 and y<LIVES_Y+14) or
(x>=LIVES_X+i*32+4 and x<LIVES_X+i*32+22 and y>=LIVES_Y+14 and y<LIVES_Y+16) or
(x>=LIVES_X+i*32+6 and x<LIVES_X+i*32+20 and y>=LIVES_Y+16 and y<LIVES_Y+18) or
(x>=LIVES_X+i*32+8 and x<LIVES_X+i*32+18 and y>=LIVES_Y+18 and y<LIVES_Y+20) or
(x>=LIVES_X+i*32+10 and x<LIVES_X+i*32+16 and y>=LIVES_Y+20 and y<LIVES_Y+22) or
(x>=LIVES_X+i*32+12 and x<LIVES_X+i*32+14 and y>=LIVES_Y+22 and y<LIVES_Y+24)
) then
VGA_R <= heartColor(0 to 3);
VGA_G <= heartColor(4 to 7);
VGA_B <= heartColor(8 to 11);
end if;
if
(
(x>=LIVES_X+i*32+4 and x<LIVES_X+i*32+6 and y>=LIVES_Y+10 and y<LIVES_Y+12) or
(x>=LIVES_X+i*32+4 and x<LIVES_X+i*32+6 and y>=LIVES_Y+4 and y<LIVES_Y+8) or
(x>=LIVES_X+i*32+6 and x<LIVES_X+i*32+8 and y>=LIVES_Y+4 and y<LIVES_Y+6)
) then
VGA_R <= X"E";
VGA_G <= X"E";
VGA_B <= X"E";
end if;
end if;
end loop;
--end draw lives
--draw brick
elsif(y>=BRICK_MATRIX_Y/UNIT and y<BRICK_HEIGHT/UNIT*BRICK_MAX_ROW+BRICK_MATRIX_Y/UNIT) then
for i in 0 to BRICK_MAX_ROW-1 loop
for k in 0 to BRICK_MAX_COL-1 loop
if(brick_matrix(i,k)/=0) then
brickX:=k*BRICK_WIDTH/UNIT+BRICK_MATRIX_X/UNIT;
brickY:=i*BRICK_HEIGHT/UNIT+BRICK_MATRIX_Y/UNIT;
brickColor:=get_brick_color(brick_matrix(i,k));
if(x>=brickX and x<brickX+BRICK_WIDTH/UNIT and y>=brickY and y<brickY+BRICK_HEIGHT/UNIT) then
VGA_R<=X"0";
VGA_G<=X"0";
VGA_B<=X"0";
if(x<brickX+BRICK_WIDTH/UNIT-2 and y<brickY+BRICK_HEIGHT/UNIT-2) then
VGA_R<=R_BRICK;
VGA_G<=G_BRICK;
VGA_B<=B_BRICK;
end if;
end if;
end if;
end loop;
end loop;
--end draw brick
else
--draw paddle
if(x>=PADDLE_X and x<PADDLE_X+PADDLE_WIDTH and y>=PADDLE_STARTING_POSY/UNIT and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT) then
--paddle black connections
if(x>=PADDLE_X+12 and x<PADDLE_X+PADDLE_WIDTH-12 and y>=PADDLE_STARTING_POSY/UNIT+2 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-2) then
VGA_R <= X"0";
VGA_G <= X"0";
VGA_B <= X"0";
end if;
--paddle center
if(x>=PADDLE_X+14 and x<PADDLE_X+PADDLE_WIDTH-14) then
VGA_R <= X"0";
VGA_G <= X"0";
VGA_B <= X"0";
if(y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-2) then
VGA_R <= X"6";
VGA_G <= X"6";
VGA_B <= X"6";
end if;
if(y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-6) then
VGA_R <= X"A";
VGA_G <= X"A";
VGA_B <= X"A";
end if;
if(y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-12) then
VGA_R <= X"E";
VGA_G <= X"E";
VGA_B <= X"E";
end if;
if(y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-16) then
VGA_R <= X"6";
VGA_G <= X"6";
VGA_B <= X"6";
end if;
end if;
--paddle red sides
if((x>=PADDLE_X+6 and x<PADDLE_X+12) or (x>=PADDLE_X+PADDLE_WIDTH-12 and x<PADDLE_X+PADDLE_WIDTH-6) or
(x>=PADDLE_X+4 and x<PADDLE_X+6 and y>=PADDLE_STARTING_POSY/UNIT+2 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-2) or
(x>=PADDLE_X+PADDLE_WIDTH-6 and x<PADDLE_X+PADDLE_WIDTH-4 and y>=PADDLE_STARTING_POSY/UNIT+2 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-2)) then
VGA_R <= X"8";
VGA_G <= X"0";
VGA_B <= X"0";
end if;
if((x>=PADDLE_X+4 and x<PADDLE_X+12 and y>=PADDLE_STARTING_POSY/UNIT+4 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-4) or
(x>=PADDLE_X+PADDLE_WIDTH-12 and x<PADDLE_X+PADDLE_WIDTH-4 and y>=PADDLE_STARTING_POSY/UNIT+4 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-4)) then
VGA_R <= X"E";
VGA_G <= X"0";
VGA_B <= X"0";
end if;
--paddle lights
if
(
(x>=PADDLE_X and x<PADDLE_X+2 and y>=PADDLE_STARTING_POSY/UNIT+6 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-6) or
(x>=PADDLE_X+2 and x<PADDLE_X+4 and y>=PADDLE_STARTING_POSY/UNIT+4 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-4) or
(x>=PADDLE_X+PADDLE_WIDTH-2 and x<PADDLE_X+PADDLE_WIDTH and y>=PADDLE_STARTING_POSY/UNIT+6 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-6) or
(x>=PADDLE_X+PADDLE_WIDTH-4 and x<PADDLE_X+PADDLE_WIDTH-2 and y>=PADDLE_STARTING_POSY/UNIT+4 and y<PADDLE_STARTING_POSY/UNIT+PADDLE_HEIGHT/UNIT-4)
)
then
VGA_R <= lightColor(0 to 3);
VGA_G <= lightColor(4 to 7);
VGA_B <= lightColor(8 to 11);
end if;
--paddle bright spots
if
(
(x>=PADDLE_X+6 and x<PADDLE_X+12 and y>=PADDLE_STARTING_POSY/UNIT+2 and y<PADDLE_STARTING_POSY/UNIT+4) or
(x>=PADDLE_X+4 and x<PADDLE_X+6 and y>=PADDLE_STARTING_POSY/UNIT+4 and y<PADDLE_STARTING_POSY/UNIT+6) or
(x>=PADDLE_X+PADDLE_WIDTH-12 and x<PADDLE_X+PADDLE_WIDTH-6 and y>=PADDLE_STARTING_POSY/UNIT+2 and y<PADDLE_STARTING_POSY/UNIT+4) or
(x>=PADDLE_X and x<PADDLE_X+2 and y>=PADDLE_STARTING_POSY/UNIT+6 and y<PADDLE_STARTING_POSY/UNIT+8) or
(x>=PADDLE_X+PADDLE_WIDTH-4 and x<PADDLE_X+PADDLE_WIDTH-2 and y>=PADDLE_STARTING_POSY/UNIT+6 and y<PADDLE_STARTING_POSY/UNIT+8)
) then
VGA_R <= X"E";
VGA_G <= X"E";
VGA_B <= X"E";
end if;
end if;
--end draw paddle
end if;
--draw powerup
case POWERUP is
when P_LIFE => powerUpColor:=get_powerup_color(P_LIFE);
when P_SLOW => powerUpColor:=get_powerup_color(P_SLOW);
when P_ENLARGE => powerUpColor:=get_powerup_color(P_ENLARGE);
when P_DEATH => powerUpColor:=get_powerup_color(P_DEATH);
when P_FAST => powerUpColor:=get_powerup_color(P_FAST);
when others =>
end case;
if(x>=POWERUP_X and x<POWERUP_X+POWERUP_WIDTH/UNIT and y>=POWERUP_Y and y<POWERUP_Y+POWERUP_HEIGHT/UNIT and POWERUP/=P_NULL) then
if((x>=POWERUP_X+2 and x<POWERUP_X+POWERUP_WIDTH/UNIT-2) or (y>=POWERUP_Y+2 and y<POWERUP_Y+POWERUP_HEIGHT/UNIT-2)) then
VGA_R<=R_POWERUP_DARK;
VGA_G<=G_POWERUP_DARK;
VGA_B<=B_POWERUP_DARK;
end if;
if((x>=POWERUP_X+4 and x<POWERUP_X+POWERUP_WIDTH/UNIT-4 and y>=POWERUP_Y+2 and y<POWERUP_Y+POWERUP_HEIGHT/UNIT-2) or
(x>=POWERUP_X+2 and x<POWERUP_X+POWERUP_WIDTH/UNIT-2 and y>=POWERUP_Y+4 and y<POWERUP_Y+POWERUP_HEIGHT/UNIT-4)) then
VGA_R<=R_POWERUP_LIGHT;
VGA_G<=G_POWERUP_LIGHT;
VGA_B<=B_POWERUP_LIGHT;
end if;
if((x>=POWERUP_X+2 and x<POWERUP_X+POWERUP_WIDTH/UNIT-4 and y>=POWERUP_Y+2 and y<POWERUP_Y+4) or
(x>=POWERUP_X+0 and x<POWERUP_X+2 and y>=POWERUP_Y+4 and y<POWERUP_Y+6)) then
VGA_R<=X"E";
VGA_G<=X"E";
VGA_B<=X"E";
end if;
end if;
--end draw powerup
--draw ball
if(x>=BALL_X and x<BALL_X+BALL_SIZE/UNIT and y>=BALL_Y and y<BALL_Y+BALL_SIZE/UNIT) then
if
(
(x>=BALL_X+4 and x<BALL_X+9 and y>=BALL_Y+0 and y<BALL_Y+13) or
(x>=BALL_X+2 and x<BALL_X+11 and y>=BALL_Y+1 and y<BALL_Y+12) or
(x>=BALL_X+1 and x<BALL_X+12 and y>=BALL_Y+2 and y<BALL_Y+11) or
(x>=BALL_X+0 and x<BALL_X+13 and y>=BALL_Y+4 and y<BALL_Y+9)
)
then
VGA_R <= COLOR_BALLBORDER(0 to 3);
VGA_G <= COLOR_BALLBORDER(4 to 7);
VGA_B <= COLOR_BALLBORDER(8 to 11);
end if;
if
(
(x>=BALL_X+5 and x<BALL_X+8 and y>=BALL_Y+2 and y<BALL_Y+11) or
(x>=BALL_X+3 and x<BALL_X+10 and y>=BALL_Y+3 and y<BALL_Y+10) or
(x>=BALL_X+2 and x<BALL_X+11 and y>=BALL_Y+5 and y<BALL_Y+8)
)
then
VGA_R <= COLOR_BALLFILL(0 to 3);
VGA_G <= COLOR_BALLFILL(4 to 7);
VGA_B <= COLOR_BALLFILL(8 to 11);
end if;
end if;
--end draw ball
--outside visible screen
else
VGA_R <= X"0";
VGA_G <= X"0";
VGA_B <= X"0";
end if;
--update coordinates
if(old_x = TOTAL_W-1) then
if(old_y = TOTAL_H-1) then
old_y := 0;
else
old_y := old_y + 1;
end if;
old_x := 0;
else
old_x := old_x + 1;
end if;
end if;
end process;
AnimationProcess : process(lightState)
begin
case lightState is
when LS_DARKER_UP=>
lightColor<=COLOR_LIGHTDARKER;
heartColor<=COLOR_HEARTDARK;
when LS_DARK_UP=>
lightColor<=COLOR_LIGHTDARK;
heartColor<=COLOR_HEARTDARK;
when LS_LIGHT_DN=>
lightColor<=COLOR_LIGHTLIGHT;
heartColor<=COLOR_HEARTLIGHT;
when LS_DARK_DN=>
lightColor<=COLOR_LIGHTDARK;
heartColor<=COLOR_HEARTLIGHT;
end case;
end process;
animation_time_generator : process(CLOCK, RESET_N)
variable counter : integer range 0 to (ANIMATION_RATE-1);
begin
if (RESET_N = '0') then
counter := 0;
changeLight <= '0';
elsif (rising_edge(CLOCK)) then
if(counter = counter'high) then
counter := 0;
changeLight <= '1';
else
counter := counter+1;
changeLight <= '0';
end if;
end if;
end process;
end architecture;

View File

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

View File

@@ -0,0 +1,2 @@
`define BUILD_DATE "181204"
`define BUILD_TIME "062230"

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,82 @@
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)
'h16: joystick[1] <= ~release_btn; // 1
'h1E: joystick[2] <= ~release_btn; // 2
'h75: joystick[4] <= ~release_btn; // arrow up
'h72: joystick[5] <= ~release_btn; // arrow down
'h6B: joystick[6] <= ~release_btn; // arrow left
'h74: joystick[7] <= ~release_btn; // arrow right
'h29: joystick[0] <= ~release_btn; // Space
'h11: joystick[1] <= ~release_btn; // Left Alt
'h0d: joystick[2] <= ~release_btn; // Tab
'h76: joystick[3] <= ~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,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 [24:0] ioctl_addr,
output reg [7:0] ioctl_dout
);
reg [7:0] b_data;
reg [6:0] sbuf;
reg [7:0] cmd;
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [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 [24:0] addr_w;
reg rclk = 0;
localparam UIO_FILE_TX = 8'h53;
localparam UIO_FILE_TX_DAT = 8'h54;
localparam UIO_FILE_INDEX = 8'h55;
// data_io has its own SPI interface to the io controller
always@(posedge SPI_SCK, posedge SPI_SS2) begin
reg [6:0] sbuf;
reg [7:0] cmd;
reg [4:0] cnt;
reg [24:0] addr;
if(SPI_SS2) cnt <= 0;
else begin
rclk <= 0;
// don't shift in last bit. It is evaluated directly
// when writing to ram
if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI};
// increase target address after write
if(rclk) addr <= addr + 1'd1;
// count 0-7 8-15 8-15 ...
if(cnt < 15) cnt <= cnt + 1'd1;
else cnt <= 8;
// finished command byte
if(cnt == 7) cmd <= {sbuf, SPI_DI};
// prepare/end transmission
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
// prepare
if(SPI_DI) begin
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,194 @@
//
// 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
);
`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 DWIDTH = HALF_DEPTH ? 2 : 5;
assign vs_out = vs_in;
reg [2:0] phase;
reg [2:0] ce_div;
reg [7:0] pix_len = 0;
wire [7:0] pl = pix_len + 1'b1;
reg ce_x1, ce_x4;
reg req_line_reset;
wire ls_in = hs_in | line_start;
always @(negedge clk_sys) begin
reg old_ce;
reg [2:0] ce_cnt;
reg [7:0] pixsz2, pixsz4 = 0;
old_ce <= ce_pix;
if(~&pix_len) pix_len <= pix_len + 1'd1;
ce_x4 <= 0;
ce_x1 <= 0;
// use such odd comparison to place c_x4 evenly if master clock isn't multiple 4.
if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin
phase <= phase + 1'd1;
ce_x4 <= 1;
end
if(~old_ce & ce_pix) begin
pixsz2 <= {1'b0, pl[7:1]};
pixsz4 <= {2'b00, pl[7:2]};
ce_x1 <= 1;
ce_x4 <= 1;
pix_len <= 0;
phase <= phase + 1'd1;
ce_cnt <= ce_cnt + 1'd1;
if(ce_pix_actual) begin
phase <= 0;
ce_div <= ce_cnt + 1'd1;
ce_cnt <= 0;
req_line_reset <= 0;
end
if(ls_in) req_line_reset <= 1;
end
end
reg ce_sd;
always @(*) begin
case(ce_div)
2: ce_sd = !phase[0];
4: ce_sd = !phase[1:0];
default: ce_sd <= 1;
endcase
end
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x
(
.clk(clk_sys),
.ce_x4(ce_x4 & ce_sd),
.inputpixel({b_in,g_in,r_in}),
.mono(mono),
.disable_hq2x(~hq2x),
.reset_frame(vs_in),
.reset_line(req_line_reset),
.read_y(sd_line),
.read_x(sd_h_actual),
.outpixel({b_out,g_out,r_out})
);
reg [10:0] sd_h_actual;
always @(*) begin
case(ce_div)
2: sd_h_actual = sd_h[10:1];
4: sd_h_actual = sd_h[10:2];
default: sd_h_actual = sd_h;
endcase
end
reg [10:0] sd_h;
reg [1:0] sd_line;
always @(posedge clk_sys) begin
reg [11:0] hs_max,hs_rise,hs_ls;
reg [10:0] hcnt;
reg [11:0] sd_hcnt;
reg hs, hs2, vs, ls;
if(ce_x1) begin
hs <= hs_in;
ls <= ls_in;
if(ls && !ls_in) hs_ls <= {hcnt,1'b1};
// falling edge of hsync indicates start of line
if(hs && !hs_in) begin
hs_max <= {hcnt,1'b1};
hcnt <= 0;
if(ls && !ls_in) hs_ls <= {10'd0,1'b1};
end else begin
hcnt <= hcnt + 1'd1;
end
// save position of rising edge
if(!hs && hs_in) hs_rise <= {hcnt,1'b1};
vs <= vs_in;
if(vs && ~vs_in) sd_line <= 0;
end
if(ce_x4) begin
hs2 <= hs_in;
// output counter synchronous to input and at twice the rate
sd_hcnt <= sd_hcnt + 1'd1;
sd_h <= sd_h + 1'd1;
if(hs2 && !hs_in) sd_hcnt <= hs_max;
if(sd_hcnt == hs_max) sd_hcnt <= 0;
// replicate horizontal sync at twice the speed
if(sd_hcnt == hs_max) hs_out <= 0;
if(sd_hcnt == hs_rise) hs_out <= 1;
if(sd_hcnt == hs_ls) sd_h <= 0;
if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1;
end
end
endmodule

View File

@@ -0,0 +1,56 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_unsigned.ALL;
entity sqrt is
port
(
CLOCK : in std_logic;
CLEAR : in std_logic;
DATA_IN : in std_logic_vector (15 downto 0);
DATA_OUT : out std_logic_vector (7 downto 0)
);
end entity;
architecture RTL of sqrt is
signal partDone : std_logic := '0';
signal partCount : integer := 7;
signal result : std_logic_vector(9 downto 0) := "0000000000";
signal partialQ : std_logic_vector(11 downto 0) := "000000000000";
begin
partDone_1: process(CLOCK,CLEAR,DATA_IN,partDone)
begin
if(rising_edge(CLOCK) and CLEAR='0')then
--square root abacus algorithm (C. Woo)
if(partDone='0')then
if(partCount>=0)then
partialQ(1 downto 0) <= DATA_IN((partCount*2)+ 1 downto partCount*2);
partDone <= '1';
else
DATA_OUT <= result(7 downto 0);
end if;
partCount <= partCount - 1;
elsif(partDone='1')then
if((result(7 downto 0) & "01") <= partialQ)then
result <= result(8 downto 0) & '1';
partialQ(9 downto 2) <= partialQ(7 downto 0) - (result(1 downto 0)&"01");
else
result <= result(8 downto 0) & '0';
partialQ(9 downto 2) <= partialQ(7 downto 0);
end if;
partDone <= '0';
end if;
end if;
if(rising_edge(CLOCK) and CLEAR='1')then
partCount <= 7;
partDone <= '0';
result <= "0000000000";
partialQ <= "000000000000";
end if;
end process;
end architecture;

View File

@@ -0,0 +1,105 @@
--Authors: Pietro Bassi, Marco Torsello
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use work.arkanoid_package.all;
package vga_package is
--types definition
subtype powerup_color_type is std_logic_vector(0 to 23);
subtype color_type is std_logic_vector(0 to 11);
--CONSTANTS
--screen
constant VISIBLE_WIDTH : natural := 640;
constant VISIBLE_HEIGHT : natural := 480;
--vertical sync
constant VERTICAL_FRONT_PORCH : natural := 10;
constant VERTICAL_SYNC_PULSE : natural := 2;
constant VERTICAL_BACK_PORCH : natural := 33;
--horizontal sync
constant HORIZONTAL_FRONT_PORCH : natural := 16;
constant HORIZONTAL_SYNC_PULSE : natural := 96;
constant HORIZONTAL_BACK_PORCH : natural := 48;
--VGA screen
constant TOTAL_H: integer := VERTICAL_FRONT_PORCH + VERTICAL_SYNC_PULSE +VERTICAL_BACK_PORCH + VISIBLE_HEIGHT; --525
constant TOTAL_W: integer := HORIZONTAL_FRONT_PORCH + HORIZONTAL_SYNC_PULSE +HORIZONTAL_BACK_PORCH + VISIBLE_WIDTH; --800
constant WINDOW_HORIZONTAL_START: integer := HORIZONTAL_FRONT_PORCH + HORIZONTAL_SYNC_PULSE; --112
constant WINDOW_HORIZONTAL_END: integer := HORIZONTAL_FRONT_PORCH + HORIZONTAL_SYNC_PULSE + VISIBLE_WIDTH; --752
constant WINDOW_VERTICAL_START: integer := VERTICAL_FRONT_PORCH + VERTICAL_SYNC_PULSE; --12
constant WINDOW_VERTICAL_END: integer := VERTICAL_FRONT_PORCH + VERTICAL_SYNC_PULSE + VISIBLE_HEIGHT;--492
--colors
constant COLOR_BKGBLUE : color_type := X"003";
constant COLOR_BKGDARKBLUE : color_type := X"002";
constant COLOR_BKGRED : color_type := X"500";
constant COLOR_BKGDARKRED : color_type := X"400";
constant COLOR_BKGGREEN : color_type := X"050";
constant COLOR_BKGDARKGREEN : color_type := X"040";
constant COLOR_BALLFILL : color_type := X"EEE";
constant COLOR_BALLBORDER : color_type := X"111";
constant COLOR_LIGHTDARKER : color_type := X"02A";
constant COLOR_LIGHTDARK : color_type := X"06D";
constant COLOR_LIGHTLIGHT : color_type := X"3CE";
constant COLOR_HEARTDARK : color_type := X"C10";
constant COLOR_HEARTLIGHT : color_type := X"E10";
--other constants
constant ANIMATION_RATE : integer := 10000000;
constant BKG_RECT_WIDTH : positive := 20;
constant BKG_RECT_HEIGHT : positive := 20;
constant LIVES_X : natural := BOUND_LAT_THICKNESS/UNIT;
constant LIVES_Y : natural := 20;
--FUNCTIONS
function get_brick_color ( brick : brick_type ) return color_type;
function get_powerup_color ( powerup : powerup_type ) return powerup_color_type;
end package;
package body vga_package is
function get_brick_color ( brick : brick_type ) return color_type is
begin
case brick is
when B_EMPTY => return X"000";
when B_WHITE => return X"FFF";
when B_ORANGE => return X"FA0";
when B_CYAN => return X"0FF";
when B_GREEN => return X"0F0";
when B_RED => return X"F00";
when B_BLUE => return X"00F";
when B_PINK => return X"F9F";
when B_PURPLE => return X"D0D";
when B_YELLOW => return X"FF0";
when B_GREY1 => return X"DDD";
when B_GREY2 => return X"BBB";
when B_GREY3 => return X"999";
when B_GREY4 => return X"777";
when B_GREY5 => return X"555";
when B_GOLD => return X"CC0";
end case;
end get_brick_color;
function get_powerup_color ( powerup : powerup_type ) return powerup_color_type is
begin
case powerup is
when P_SLOW => return X"0F00D0";
when P_FAST => return X"F00D00";
when P_LIFE => return X"00F00D";
when P_ENLARGE => return X"FF0DD0";
when P_DEATH => return X"555333";
when P_NULL => return X"000000";
end case;
end get_powerup_color;
end vga_package;

View File

@@ -0,0 +1,246 @@
//
//
// 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;
// Scanline FIX
reg [DWIDTH:0] Rd,Gd,Bd;
always @(posedge clk_sys) {Rd,Gd,Bd} <= {R,G,B};
// Scanline FIX
scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler
(
.*,
.hs_in(HSync),
.vs_in(VSync),
.r_in(Rd),
.g_in(Gd),
.b_in(Bd),
.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

@@ -11,7 +11,7 @@ Arcade Cores
#Atari Centipede Hardware
Centipede
#Atari Discrete Logic Hardware
#Atari Discrete Logic
Computer Space
#Custom Hardware
@@ -67,6 +67,7 @@ Arcade Cores
#Non Arcade
2048
Arkanoid
FlappyBird
River Raid(Clone)

View File

@@ -249,7 +249,7 @@ galaksija_video(
{3'b010,16'b10xxxxxxxxxxxxxx}: begin idata = mram3_out; rd_mram3 = 1'b1; end
{3'b100,16'b10xxxxxxxxxxxxxx}: wr_mram3= 1'b1;
//$E000...$FFFF — ROM "3" + "4" IC13: 8 KB Graphic primitives in BASIC language, Full Screen Source Editor and soft scrolling
{3'b010,16'b1110000000000000}: begin idata = rom3_out; rd_rom3 = 1'b1; end
{3'b010,16'b111xxxxxxxxxxxxx}: begin idata = rom3_out; rd_rom3 = 1'b1; end
default : begin end
endcase
end