mirror of
https://github.com/MiSTer-devel/Arcade-ComputerSpace_MiSTer.git
synced 2026-04-19 03:02:33 +00:00
1459 lines
58 KiB
VHDL
1459 lines
58 KiB
VHDL
-----------------------------------------------------------------------------
|
|
-- SYNC STAR BOARD --
|
|
-- For use with Computer Space FPGA emulator --
|
|
-- Implementation of Computer Space's Sync Star Board --
|
|
-- "wire by wire" and "component by component"/"gate by gate" based on --
|
|
-- original schematics. --
|
|
-- With exceptions regarding: --
|
|
-- > start/stop & replay logic (impl as state machine instead) --
|
|
-- > analogue/discrete based timers (impl as counters) --
|
|
-- > scan counter, sync and star generation logic --
|
|
-- - implemented in separate entity to provide interlaced ntsc --
|
|
-- video and overcome Signetics 74161 deviation that impacts --
|
|
-- star generation --
|
|
-- > all flip flops which use asynch clock inputs are replaced with --
|
|
-- flip flops driven by high freq clock and logic to identify --
|
|
-- edge changes on the logical clock input --
|
|
-- --
|
|
-- There are plenty of comments throughout the code to make it easier to --
|
|
-- understand the logic, but due to the sheer number of comments there --
|
|
-- may exist occasional mishaps. --
|
|
-- --
|
|
-- This entity is implementation agnostic. --
|
|
-- --
|
|
-- Naming convention: --
|
|
-- Signals are labelled after the component that generates the signal; --
|
|
-- more specifically the component's schematics label and the specific --
|
|
-- output. For instance: NOR gate F6 and its output pin 10 generate a --
|
|
-- signal which will be labelled f6_10. --
|
|
-- Occasionally signals are labelled after a component input - this is --
|
|
-- most common for components where the input is exposed --
|
|
-- to "component-internal processing" beyond simple gate functionality, --
|
|
-- such as bistable latches, counters, flip-flops and multiplexers. --
|
|
-- Sync Star Board inputs/outputs are labelled SB_<nn>, where <nn> is --
|
|
-- according to original schematics input/output labels. --
|
|
-- --
|
|
-- v1.0 --
|
|
-- by Mattias G, 2015 --
|
|
-- Enjoy! --
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
|
library ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
use ieee.std_logic_arith.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
library work;
|
|
|
|
--80--------------------------------------------------------------------------|
|
|
|
|
|
|
entity sync_star_board is
|
|
port (
|
|
reset,
|
|
game_clk -- Fundamental game
|
|
-- clock for the whole game's
|
|
-- logical timing
|
|
-- Only used when
|
|
-- video_signal_type is
|
|
-- set to '1' (ie emulating
|
|
-- original video signalling)
|
|
: in std_logic;
|
|
super_clk, -- Clock to emulate
|
|
-- asynch flip flop logic
|
|
|
|
explosion_clk,
|
|
seconds_clk : in std_logic;
|
|
|
|
SB_3, -- Saucer Enable
|
|
-- signals that the TV beam
|
|
-- is "sweeping" by the current
|
|
-- position of one of the
|
|
-- two 16 x 8 pixel
|
|
-- saucer image grids
|
|
SB_4, -- Saucer Missile
|
|
-- signals that the TV beam
|
|
-- is "sweeping" by the current
|
|
-- pixel position of an active
|
|
-- saucer missile
|
|
SB_6, -- Rocket Missile
|
|
-- signals that the TV beam
|
|
-- is "sweeping" by the current
|
|
-- pixel position of an active
|
|
-- rocket missile
|
|
SB_7, -- "start button pressed" signal
|
|
SB_C, -- "coin inserted" signal
|
|
SB_D, -- 2PlayPerCoin SW
|
|
SB_E, -- Rocket Enable
|
|
-- signals that the TV beam
|
|
-- is "sweeping" by the current
|
|
-- position of the 16 x 16 pixel
|
|
-- rocket image grid
|
|
SB_F, -- Replay SW
|
|
SB_N -- rocket & saucer video mix signal
|
|
: in std_logic;
|
|
|
|
SB_2, -- Saucer Video Enable
|
|
-- active when saucer
|
|
-- can be drawn onto screen (ie its not
|
|
-- in the "pause" state after a
|
|
-- hit or collision)
|
|
SB_5, -- Rocket Video Enable
|
|
-- active when rocket
|
|
-- can be drawn onto screen (ie its not
|
|
-- in the "pause" state after an
|
|
-- explosion or collision, and its
|
|
-- ongoing game play)
|
|
SB_H, -- Count Enable
|
|
-- active during the
|
|
-- visible part of the screen to signal
|
|
-- that objects can be moved and drawn
|
|
-- onto screen
|
|
SB_K, -- audio gate; active when game is on
|
|
-- to open up for audio
|
|
SB_L, -- signal to trigger explosion
|
|
-- audio sample
|
|
SB_M, -- spin; signal to spin rocket
|
|
-- after being hit by saucer missile,
|
|
-- active when spinning
|
|
SB_Y -- inverse clock out
|
|
: out std_logic;
|
|
|
|
-- signals for
|
|
-- composite video / instead of SB_20
|
|
hsync : out std_logic;
|
|
vsync : out std_logic;
|
|
composite_video_signal : out std_logic_vector(3 downto 0);
|
|
hblank,vblank : out std_logic
|
|
);
|
|
|
|
end sync_star_board;
|
|
|
|
architecture sync_star_board_architecture of
|
|
sync_star_board is
|
|
|
|
component scan_counter is
|
|
port (
|
|
game_clk : in std_logic;
|
|
hsync : out std_logic;
|
|
vsync : out std_logic;
|
|
star_video_out : out std_logic;
|
|
count_enable : out std_logic;
|
|
hblank,vblank : out std_logic;
|
|
b2_12 : out std_logic;
|
|
vertical, horizontal : out std_logic_vector (7 downto 0)
|
|
);
|
|
end component;
|
|
|
|
signal count_enable, a1_15, c4_14 : std_logic;
|
|
|
|
-- signals for score & time display logic
|
|
signal j4_8, j2_8, h3_8, h3_6, j3_8,
|
|
j3_6, j3_12, h3_12 : std_logic;
|
|
signal g3_9, g3_10, g3_11, g3_12,
|
|
g3_13, g3_14, g3_15 : std_logic;
|
|
signal e5_2 : std_logic;
|
|
|
|
signal g3_out : std_logic_vector (6 downto 0);
|
|
signal g3_in : std_logic_vector (3 downto 0);
|
|
|
|
signal g1_8, d2_13, d2_10, c2_6 : std_logic;
|
|
signal d1_11, d1_12, d1_13, c1_11,
|
|
c1_12, c1_13 : std_logic;
|
|
signal c2_3 : std_logic;
|
|
signal g3_7, g3_1, g3_2, g3_6 : std_logic;
|
|
signal f1_11, f1_12, f1_13, f1_14,
|
|
e1_11, e1_12, e1_13, e1_14 : std_logic;
|
|
signal j2_6, h1_8, g1_6, f2_6, g2_8,
|
|
g2_6, e2_6, e2_8, b2_2, d2_4,
|
|
d2_1 : std_logic;
|
|
signal h2_13, h2_4, h2_10, g1_12, h1_3 : std_logic;
|
|
|
|
signal horizontal_position : std_logic_vector (7 downto 0)
|
|
:= "00000000";
|
|
signal vertical_position : std_logic_vector (7 downto 0)
|
|
:= "00000000";
|
|
|
|
-- signals for score and time keeping
|
|
signal f3_3, f3_4, f3_5, f3_6,
|
|
f3_10, f3_11, f3_12, f3_13,
|
|
f3_14, f3_2, f3_7, f3_9 : std_logic;
|
|
signal a3_3, a3_4, a3_5,
|
|
a3_6, a3_10, a3_11, a3_12,
|
|
a3_13, a3_14, a3_2, a3_7, a3_9 : std_logic;
|
|
|
|
|
|
signal d3_14, d3_2 : std_logic;
|
|
signal e3_14, e3_2 : std_logic;
|
|
signal h1_6, c5_6, e5_8 : std_logic;
|
|
signal e3_12, e3_11, e3_9, e3_8 : std_logic;
|
|
signal d3_12, d3_11, d3_9, d3_8 : std_logic;
|
|
signal c3_14, c3_2, c3_12, c3_11,
|
|
c3_9, c3_8 : std_logic;
|
|
signal b3_14, b3_2, b3_12,
|
|
b3_11, b3_9, b3_8 : std_logic;
|
|
|
|
signal b3_count : std_logic_vector (3 downto 0);
|
|
signal c3_count : std_logic_vector (3 downto 0);
|
|
signal d3_count : std_logic_vector (3 downto 0);
|
|
signal e3_count : std_logic_vector (3 downto 0);
|
|
signal a2_A, a2_B : std_logic_vector (3 downto 0);
|
|
|
|
-- signals for replay
|
|
signal a2_3, a2_4, a2_5, a2_6,
|
|
a2_10, a2_11, a2_12,
|
|
a2_13, a2_15 : std_logic;
|
|
signal c2_11 : std_logic;
|
|
|
|
-- signals for explosion circuitry logic
|
|
signal a6_8, h2_1, a6_3, a6_11,
|
|
a6_6, e2_13, e2_4,
|
|
e2_10, j5_3, c5_8, c5_11 : std_logic;
|
|
signal b6_1 : std_logic :='1';
|
|
signal b5_11, b5_13, b5_12 : std_logic;
|
|
signal b5_3, b5_1, b5_2 : std_logic;
|
|
signal a5_3, a5_1, a5_2 : std_logic;
|
|
signal a4_12, d4_6 : std_logic;
|
|
signal b4_1, b4_3, b4_4, b4_16 : std_logic;
|
|
signal b4_6, b4_9, b4_12, b4_8 : std_logic;
|
|
signal c4_6, c4_9, c4_12, c4_8 : std_logic;
|
|
|
|
-- q output from flip flops that
|
|
-- need initial value
|
|
signal a5_5, b5_5, b5_9,
|
|
b4_15, b4_11, c4_11 : std_logic :='0';
|
|
|
|
-- qn output from flip flops that
|
|
-- need initial value
|
|
signal a5_6, b5_6, b5_8, b4_10, c4_10 : std_logic :='1';
|
|
|
|
signal a4_8, a4_6, d4_8, j1_6 : std_logic;
|
|
signal a5_3_1, b5_3_1, b5_11_13,
|
|
c4_6_8, b4_6_8, b4_1_3 : std_logic;
|
|
|
|
-- signals for start/end game
|
|
-- circuitry logic
|
|
signal SB_B : std_logic;
|
|
signal SB_7_old : std_logic :='1';
|
|
signal SB_C_old : std_logic :='1';
|
|
|
|
-- game clock
|
|
signal b2_12 : std_logic;
|
|
|
|
signal e3_10, c5_3 : std_logic;
|
|
signal e5_12 : std_logic :='1';
|
|
signal d6_6 : std_logic :='0';
|
|
signal d6_8 : std_logic :='1';
|
|
signal a5_11, a5_12, a5_10 : std_logic;
|
|
signal a5_9 : std_logic :='0';
|
|
signal a5_8 : std_logic :='1';
|
|
signal c2_8 : std_logic;
|
|
signal d5_1, d5_3, d5_2 : std_logic;
|
|
signal e5_10 : std_logic := '0';
|
|
signal d5_6 : std_logic :='1';
|
|
signal d5_13, d5_11, d5_12, d5_10 : std_logic;
|
|
signal d5_9 : std_logic := '0';
|
|
signal d5_8 : std_logic := '1';
|
|
signal c6_5, c6_5_old, c6_6, c6_1, c6_1_old : std_logic;
|
|
|
|
-- signals to manage asynchronous
|
|
-- clock design embedded in
|
|
-- synchronous clk solutions
|
|
signal b5_3_old, a5_3_old : std_logic;
|
|
signal c4_6_old, b4_6_old,
|
|
b4_1_old, b5_11_old : std_logic;
|
|
signal d5_11_old, d5_3_old : std_logic := '1';
|
|
-- set to initial '1' as the initial
|
|
-- signal is also '1',
|
|
-- to avoid trigger of game
|
|
-- start directly
|
|
|
|
signal e3_14_old, d3_14_old,
|
|
c3_14_old, b3_14_old : std_logic := '0';
|
|
|
|
-- signal for composite
|
|
-- star video generation
|
|
signal star_video : std_logic;
|
|
|
|
-- signals for external buttons
|
|
-- and coin mechanism
|
|
signal signal_ccw, signal_cw,
|
|
signal_thrust, signal_fire,
|
|
signal_start, signal_coin : std_logic;
|
|
|
|
-----------------------------------------------------------------------------//
|
|
begin
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Game Clock Mapping --
|
|
-----------------------------------------------------------------------------
|
|
SB_Y <= not b2_12; -- new
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Composite video sync, scan counter, star generation, game clock --
|
|
-- Corresponds to: --
|
|
-- Sync Counter: D1, E1, C4 (pin 1-4 / 14-16), C1, F1 --
|
|
-- b2_6, b2_4, h1_11 --
|
|
-- Sync Generator: j2_12, j1_3, f2_8, j1_11 --
|
|
-- Star Generator: B1, A1, b2_8 --
|
|
-- Game Clock: b2_12 --
|
|
-- --
|
|
-- Logic that provides either original video signalling or interlaced --
|
|
-- ntsc video signal. As it is not according to original schematics it is --
|
|
-- placed in a separate entity to isolate from rest of original --
|
|
-- schematics. Functionally it will provide "black box" output --
|
|
-- identical to Computer Space game logic behaviour. --
|
|
-- --
|
|
-- Star generation also resides in the same entity to emulate a --
|
|
-- "deviation" in the Signetics 74161 chip, that Computer Space uses, --
|
|
-- versus the "standard" 74161 implementations. --
|
|
-- The Signetics 74161 allows one counter increment when ENT is low, --
|
|
-- in the case ENT goes low when the clock is also low. --
|
|
-- "Standard" 74161 (eg TI and others) prohibits increments all the time --
|
|
-- when ENT is low. --
|
|
-- The star layout on screen is a result of this deviation in Signetics --
|
|
-- implementation of the 74161 counter. A deviation that took a very long --
|
|
-- time to uncover. It was not until measurement data from a real --
|
|
-- Computer Space Board was compared with standard 74161 chip behaviour --
|
|
-- that this piece of the puzzle was solved. --
|
|
-----------------------------------------------------------------------------
|
|
sync_and_stars: component scan_counter
|
|
port map(game_clk, hsync, vsync, star_video,
|
|
count_enable, hblank, vblank, b2_12, vertical_position,
|
|
horizontal_position);
|
|
|
|
a1_15 <= star_video;
|
|
SB_H <= count_enable;
|
|
--c4_14 <= count_enable;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Assign counter value from scan counters --
|
|
-----------------------------------------------------------------------------
|
|
d1_11 <= horizontal_position (3);
|
|
d1_12 <= horizontal_position (2);
|
|
d1_13 <= horizontal_position (1);
|
|
|
|
e1_11 <= horizontal_position (7);
|
|
e1_12 <= horizontal_position (6);
|
|
e1_13 <= horizontal_position (5);
|
|
e1_14 <= horizontal_position (4);
|
|
|
|
c1_11 <= vertical_position (3);
|
|
c1_12 <= vertical_position (2);
|
|
c1_13 <= vertical_position (1);
|
|
|
|
f1_11 <= vertical_position (7);
|
|
f1_12 <= vertical_position (6);
|
|
f1_13 <= vertical_position (5);
|
|
f1_14 <= vertical_position (4);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COMPOSITE VIDEO OUT --
|
|
-- Replaces the entire discrete electronics video part in the schematics --
|
|
-- including SB_20 - except for sync signal (which is a separate signal) --
|
|
-- note j1_6 is steering inverse or not --
|
|
-- a1_15 is star video NORMAL --
|
|
-- e5_2 is score & time dislay video signal NORMAL --
|
|
-- c4_14 is count enable --
|
|
-- SB_N is rocket/saucer video signal --
|
|
-- j5_3 is rocket/saucer missile video signal --
|
|
-----------------------------------------------------------------------------
|
|
--composite_video_signal <= c4_14 and -- count enable
|
|
-- (j1_6 xor (SB_N or e5_2 or a1_15 or j5_3));
|
|
|
|
composite_video_signal <= j1_6 & (SB_N or j5_3 ) & e5_2 & a1_15; -- DarFPGA 2017
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Seven Segment Display Video --
|
|
-- Outputs the right seven-segment "pixels" depending on where the --
|
|
-- TV beam is currently positioned --
|
|
-- Essentially it decodes the horizontal and vertical position bits (0-3) --
|
|
-- to map segment by segment --
|
|
-----------------------------------------------------------------------------
|
|
j2_8 <= not (g3_9 and c1_11 and d2_13); -- segment e
|
|
|
|
h3_8 <= not (g3_10 and c1_11 and c2_6); -- segment d
|
|
|
|
h3_6 <= not (g3_11 and c1_11 and c2_3); -- segment c
|
|
|
|
j3_8 <= not (g3_12 and g1_8 and c2_3); -- segment b
|
|
|
|
j3_6 <= not (g3_13 and g1_8 and d2_10); -- segment a
|
|
|
|
j3_12 <= not (g3_14 and g1_8 and c2_6); -- segment f
|
|
|
|
h3_12 <= not (g3_15 and g1_8 and d2_13); -- segment g
|
|
|
|
j4_8 <= not (j2_8 and h3_8 and h3_6 and -- segment video mix signal
|
|
j3_8 and j3_6 and j3_12 and
|
|
h3_12);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: BCD-TO-SEVEN-SEGMENT DECODER --
|
|
-- G3 7448 --
|
|
-- BCD-TO-SEVEN-SEGMENT DECODERS/DRIVERS --
|
|
-- 448 pin 1=b, pin 2=c, pin 6=d, pin 7=a --
|
|
-- --
|
|
-- Decode 4 bit binary into a set of active segments that represent --
|
|
-- decimal characters (0-9), six strange symbols and one complete blank. --
|
|
-- There are seven segments; a - g represented by 7 outputs (abcdefg). --
|
|
-- All segments active = 11111111 (abcdefg) --
|
|
-- no segment active = 0000000 (abcdefg) --
|
|
-- --
|
|
-- ---------------- EXAMPLES --------------- --
|
|
-- --
|
|
-- 8 = 1000 0 = 0000 2 = 0010 --
|
|
-- a => 1111111 => 1111110 => 1101101 --
|
|
-- ----- ----- ----- ----- --
|
|
-- I I I I I I I --
|
|
-- f I I b I I I I I --
|
|
-- --g-- ----- ----- --
|
|
-- I I I I I I I --
|
|
-- e I I c I I I I I --
|
|
-- ----- ----- ----- ----- --
|
|
-- d --
|
|
-- --
|
|
-----------------------------------------------------------------------------
|
|
--g3_7 <= a3_7; -- flawed original schematics
|
|
-- connects the wrong bits from the time&score
|
|
-- keeping part
|
|
g3_7 <= a3_9; -- revised connection logic for bit 0
|
|
|
|
--g3_1 <= a3_9; -- flawed original schematics
|
|
-- connects the wrong bits from the time&score
|
|
-- keeping part
|
|
g3_1 <= a3_7; -- revised connection logic for bit 1
|
|
|
|
g3_2 <= f3_9; -- bit 3
|
|
g3_6 <= f3_7; -- bit 4
|
|
|
|
g3_in (0) <= g3_7; -- input a
|
|
g3_in (1) <= g3_1; -- input b
|
|
g3_in (2) <= g3_2; -- input c
|
|
g3_in (3) <= g3_6; -- input d
|
|
|
|
g3_out <=
|
|
"1111110" when g3_in = "0000" else
|
|
"0110000" when g3_in = "0001" else
|
|
"1101101" when g3_in = "0010" else
|
|
"1111001" when g3_in = "0011" else
|
|
"0110011" when g3_in = "0100" else
|
|
"1011011" when g3_in = "0101" else
|
|
"0011111" when g3_in = "0110" else
|
|
"1110000" when g3_in = "0111" else
|
|
"1111111" when g3_in = "1000" else
|
|
"1110011" when g3_in = "1001" else
|
|
"0001101" when g3_in = "1010" else
|
|
"0011001" when g3_in = "1011" else
|
|
"0100011" when g3_in = "1100" else
|
|
"1001011" when g3_in = "1101" else
|
|
"0001111" when g3_in = "1110" else
|
|
"0000000" ;
|
|
|
|
-- segment output
|
|
g3_13 <= g3_out (6); --output segment a
|
|
g3_12 <= g3_out (5); --output segment b
|
|
g3_11 <= g3_out (4); --output segment c
|
|
g3_10 <= g3_out (3); --output segment d
|
|
g3_9 <= g3_out (2); --output segment e
|
|
g3_15 <= g3_out (1); --output segment f
|
|
g3_14 <= g3_out (0); --output segment g
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Segment display position input --
|
|
-- Logic to determine when the TV beam's current position matches the --
|
|
-- position required for individual segments and their "pixels" --
|
|
-- Essentially it decodes the horizontal and vertical position bits (0-3) --
|
|
-----------------------------------------------------------------------------
|
|
c2_6 <= c1_12 and c1_13;
|
|
d2_10 <= c1_12 nor c1_13;
|
|
d2_13 <= d1_13 nor d1_12;
|
|
c2_3 <= d1_13 and d1_12;
|
|
|
|
g1_8 <= not c1_11;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Rocket/Saucer Score and Time Video Enable --
|
|
-- logic to determine when the TV beam is currently at the vertical --
|
|
-- and horizontal position interval of the screen where either rocket --
|
|
-- score, saucer score or time (tens & unit) shall be be displayed --
|
|
-----------------------------------------------------------------------------
|
|
j2_6 <= not ( g2_6 and g2_8 and f2_6); -- flag that signals that
|
|
-- either rocket score, saucer
|
|
-- score or time (tens&unit) can
|
|
-- be displayed
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Score & Time Video Out --
|
|
-----------------------------------------------------------------------------
|
|
h1_3 <= j4_8 nand j2_6; -- j4_8 is the "seven segment" video signal
|
|
-- containing the current pixel (black or white)
|
|
-- to display, given the TV beam's current
|
|
-- position, to "draw" score/time characters on
|
|
-- screen
|
|
-- j2_6 is a flag that indicates whether
|
|
-- either rocket score, saucer score or time
|
|
-- (tens & unit) should be displayed or not
|
|
-- (to avoid characters being repeated across
|
|
-- the screen)
|
|
e5_2 <= not h1_3; -- Score & Time video out signal (inversed to
|
|
-- comply with downstream logic's active level)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: UNIT Display Enable --
|
|
-- logic to determine when the TV beam is currently at the horizontal --
|
|
-- position interval of the screen where UNITS shall be displayed --
|
|
-----------------------------------------------------------------------------
|
|
b2_2 <= not e1_14;
|
|
|
|
d2_4 <= d1_11 nor b2_2;
|
|
|
|
e2_8 <= not (e1_11 and e1_12 and e1_13 and d2_4); -- flag signals UNIT
|
|
-- can be displayed
|
|
|
|
g1_6 <= not e2_8; -- flag signals UNIT
|
|
-- can be displayed
|
|
-- (set to inverse
|
|
-- to fit downstream
|
|
-- active level logic)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: TENS Display Enable --
|
|
-- logic to determine when the TV beam is currently at the horizontal --
|
|
-- position interval of the screen where TENS shall be displayed --
|
|
-----------------------------------------------------------------------------
|
|
d2_1 <= e1_14 nor d1_11;
|
|
|
|
e2_6 <= not (e1_11 and e1_12 and e1_13 and d2_1); -- Flag signals TENS
|
|
-- can be displayed
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: TENS and UNIT Display Enable --
|
|
-- logic to determine when the TV beam is currently at the horizontal --
|
|
-- position interval of the screen where TENS or UNIT shall be displayed --
|
|
-----------------------------------------------------------------------------
|
|
h1_8 <= e2_6 nand e2_8; -- flag that signals that the TV beam's current
|
|
-- horizontal position is either passing
|
|
-- by the TENS position or UNIT position
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Rocket Score Display Enable --
|
|
-- logic to determine when the TV beam is currently at the vertical --
|
|
-- and horizontal position interval of the screen where rocket score shall --
|
|
-- be displayed --
|
|
-----------------------------------------------------------------------------
|
|
g1_12 <= not f1_12;
|
|
|
|
h2_10 <= f1_11 nor g1_12;
|
|
|
|
g2_8 <= not (g1_6 and f1_14 and f1_13 and h2_10); -- g1_6 indicates
|
|
-- proper horizontal
|
|
-- position interval
|
|
-- (for UNIT)
|
|
-- f1_11, f1_12, h2_10
|
|
-- indicate proper
|
|
-- vertical position
|
|
-- interval
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Saucer Score Display Enable --
|
|
-- logic to determine when the TV beam is currently at the vertical and --
|
|
-- horizontal position interval of the screen where saucer score shall --
|
|
-- be displayed --
|
|
-----------------------------------------------------------------------------
|
|
h2_13 <= f1_13 nor f1_11;
|
|
|
|
g2_6 <= not (g1_6 and f1_14 and f1_12 and h2_13); -- g1_6 indicates
|
|
-- proper horizontal
|
|
-- position interval
|
|
-- (for UNIT)
|
|
-- f1_11, f1_13, h2_13
|
|
-- indicate proper
|
|
-- vertical position
|
|
-- interval
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Time Display Enable --
|
|
-- logic to determine when the TV beam is currently at the vertical and --
|
|
-- horizontal position interval of the screen where TIME shall be --
|
|
-- displayed (both TENS and UNIT) --
|
|
-----------------------------------------------------------------------------
|
|
h2_4 <= f1_13 nor f1_12;
|
|
|
|
f2_6 <= not (h1_8 and h2_4 and f1_11 and f1_14); -- h1_8 indicates
|
|
-- proper horizontal
|
|
-- position interval
|
|
-- (for UNIT & TENS)
|
|
-- h2_4, f1_11, f1_14
|
|
-- indicate proper
|
|
-- vertical position
|
|
-- interval
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Saucer Display Enable Logic --
|
|
-- verify that saucer can actually be displayed --
|
|
-----------------------------------------------------------------------------
|
|
a6_8 <= SB_3 nand b6_1; -- SB_3 is saucer_enable from Motion Board
|
|
-- that signals that the TV beam's position is
|
|
-- passing by any of the two saucer's 16x8 image
|
|
-- grid pixels' positions
|
|
-- b6_1 is flagging whether the saucer should
|
|
-- be visible or not (delay after collision
|
|
-- or hit)
|
|
|
|
SB_2 <= a6_8; -- Saucer Enable to Memory Board
|
|
-- it is ok to display
|
|
-- saucer video image
|
|
-- (not to be confused with Saucer Enable
|
|
-- from Motion Board)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Rocket Display Enable Logic --
|
|
-- verify that the rocket can actually be displayed --
|
|
-----------------------------------------------------------------------------
|
|
h2_1 <= SB_E nor c5_8; -- SB_E is Rocket Enable from Motion Board
|
|
-- that signals that the TV beam's position is
|
|
-- passing by any of the rocket's 16x16 image
|
|
-- grid pixels' positions
|
|
-- c5_8 is flagging whether the rocket should
|
|
-- be visible or not (delay after collision
|
|
-- or hit)
|
|
|
|
a6_11 <= h2_1 nand d5_9; -- Verifies that a game is playing (d5_9)
|
|
-- otherwise the rocket will not be
|
|
-- displayed
|
|
|
|
SB_5 <= a6_11; -- Rocket Enable to Memory Board
|
|
-- it is ok to display
|
|
-- rocket video image
|
|
-- (not to be confused with Rocket Enable
|
|
-- from Motion Board)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Saucer Missile Video Enable Logic --
|
|
-- verify whether saucer missile can be displayed or not --
|
|
-- if a game is on then missile will be displayed, otherwise not --
|
|
-----------------------------------------------------------------------------
|
|
a6_3 <= SB_4 nand d5_9; -- SB_4 is saucer_missile video out
|
|
-- which is active when the TV beam's position
|
|
-- is passing by the missile pixel position
|
|
-- d5_9 is flagging whether a game is on or not
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Rocket Missile Video Enable Logic --
|
|
-- verify whether rocket missile can be displayed or not --
|
|
-- if a game is on then missile will be displayed, otherwise not --
|
|
-----------------------------------------------------------------------------
|
|
a6_6 <= SB_6 nand d5_9; -- SB_6 is rocket_missile video out
|
|
-- which is active when the TV beam's position
|
|
-- is passing by the missile pixel position
|
|
-- d5_9 is flagging whether a game is or or not
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Rocket and Saucer Missile Video Out --
|
|
-----------------------------------------------------------------------------
|
|
j5_3 <= a6_3 nand a6_6; -- saucer and rocket missile video out
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Detect collision and missile hit --
|
|
-----------------------------------------------------------------------------
|
|
e2_13 <= a6_3 nor a6_11; -- detects rocket hit by saucer missile
|
|
e2_4 <= a6_8 nor a6_6; -- detects saucer hit by rocket missile
|
|
e2_10 <= a6_11 nor a6_8; -- detects rocket colliding with saucer
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Saucer Visible or Not? --
|
|
-----------------------------------------------------------------------------
|
|
b6_1 <= b5_9 nor b5_5; -- flags whether saucer should be visible or not
|
|
-- It is not visible for a period of time
|
|
-- after it has collided with the rocket or
|
|
-- it has been hit by a rocket missile
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Rocket Visible or Not? --
|
|
-----------------------------------------------------------------------------
|
|
c5_11 <= a5_5 nand c4_11; -- signals that saucer should not be visible for
|
|
-- a period of time after rocket has been spinning
|
|
-- (following being hit by saucer missile)
|
|
|
|
c5_8 <= b5_8 nand c5_11; -- signals that saucer should not be visible
|
|
-- for a period of time
|
|
-- after it has collided with a saucer (b5_8)
|
|
-- or it has been hit by a saucer missile (c5_11)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Rocket & Saucer Collision Flag --
|
|
-- 7474, B5, pin 8-13 --
|
|
-- dual d-type pos edge triggered flipflop w preset & clear --
|
|
-- pin 13 2clrn --
|
|
-- pin 12 2d --
|
|
-- pin 11 2clk --
|
|
-- pin 10 2pren --
|
|
-- pin 9 2q --
|
|
-- pin 8 2qn --
|
|
-- --
|
|
-- Flag is set when rocket and saucer collide, and reset back to normal --
|
|
-- after a while by a timer signal (a4_8) --
|
|
-----------------------------------------------------------------------------
|
|
b5_11 <= e2_10; -- instant collision detection feeds clk
|
|
b5_13 <= a4_8; -- timer signal a4_8 feeds clrn
|
|
|
|
-- Check if Rocket has collided with Saucer
|
|
process (super_clk, b5_13)
|
|
begin
|
|
if b5_13 = '0' then -- clrn
|
|
b5_9 <= '0';
|
|
-- q is cleared when clrn is active low,
|
|
-- as pren is permanently high
|
|
|
|
b5_8 <= '1';
|
|
-- qn is cleared when clrn is active low,
|
|
-- as pren is permanently high
|
|
elsif rising_edge (super_clk) then
|
|
b5_11_old <= b5_11;
|
|
if (b5_11_old = '0') and (b5_11 = '1') then
|
|
b5_9 <= '1';
|
|
b5_8 <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Saucer Hit By Rocket Missile Flag --
|
|
-- 7474, B5, pin 1-6 --
|
|
-- dual d-type pos edge triggered flipflop w preset & clear --
|
|
-- pin 1 1clrn --
|
|
-- pin 2 1d --
|
|
-- pin 3 1clk --
|
|
-- pin 4 1pren --
|
|
-- pin 5 1q --
|
|
-- pin 6 1qn --
|
|
-- --
|
|
-- Flag is set when saucer is hit by rocket missile and reset back to --
|
|
-- normal after a while by a timer signal (a4_8) --
|
|
-----------------------------------------------------------------------------
|
|
b5_3 <= e2_4; -- instant missile hit detection feeds clk
|
|
b5_1 <= a4_8; -- timer signal a4_8 feeds clrn
|
|
|
|
-- check if Saucer is hit by Rocket missile
|
|
process (super_clk, b5_1)
|
|
begin
|
|
if b5_1 = '0' then -- clrn
|
|
b5_5 <= '0';
|
|
-- q is cleared when clrn is active low, as pren is permanently high
|
|
|
|
b5_6 <= '1';
|
|
-- qn is cleared when clrn is active low, as pren is permanently high
|
|
|
|
elsif rising_edge (super_clk) then
|
|
b5_3_old <= b5_3;
|
|
if (b5_3_old = '0') and (b5_3 = '1') then
|
|
b5_5 <= '1';
|
|
b5_6 <= '0'; -- signal to increase score for rocket player
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Rocket hit by Saucer Missile Flag --
|
|
-- 7474, A5, pin 1-6 --
|
|
-- dual d-type pos edge triggered flipflop w preset & clear --
|
|
-- pin 1 1clrn --
|
|
-- pin 2 1d --
|
|
-- pin 3 1clk --
|
|
-- pin 4 1pren --
|
|
-- pin 5 1q --
|
|
-- pin 6 1qn --
|
|
-- --
|
|
-- Flag is set when rocket is hit by saucer missile and reset back to --
|
|
-- normal after a while by a timer signal (a4_8) --
|
|
-----------------------------------------------------------------------------
|
|
a5_3 <= e2_13; -- instant missile hit detection feeds clk
|
|
a5_1 <= a4_8; -- timer signal a4_8 feeds clrn
|
|
|
|
-- Check if Rocket has been hit by Saucer missile
|
|
process (super_clk, a5_1)
|
|
begin
|
|
if a5_1 = '0' then -- clrn
|
|
a5_5 <= '0';
|
|
-- q is cleared when clrn is active low,
|
|
-- as pren is permanently high
|
|
|
|
a5_6 <= '1';
|
|
-- qn is cleared when clrn is active low,
|
|
-- as pren is permanently high
|
|
|
|
elsif rising_edge (super_clk) then
|
|
a5_3_old <= a5_3;
|
|
if (a5_3_old = '0') and (a5_3 = '1')then
|
|
a5_5 <= '1';
|
|
a5_6 <= '0'; -- signal to increase score for saucer
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Rocket spin signal --
|
|
-----------------------------------------------------------------------------
|
|
SB_M <= a5_5; -- spin
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Collision & Explosion Timer Signal --
|
|
-- Signals when the rocket or saucer has been hit by a missile or rocket --
|
|
-- and saucer have collided --
|
|
-- The signal triggers downstream collision timer to start counting the --
|
|
-- time for collision/explosion "events" --
|
|
-----------------------------------------------------------------------------
|
|
a4_12 <= not (a5_6 and b5_6 and b5_8);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Fundamental clock --
|
|
-- Creates the fundamental pulse train for timing collision and --
|
|
-- explosion events --
|
|
-----------------------------------------------------------------------------
|
|
d4_6 <= explosion_clk;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Frequency divider logic flipflop 1 --
|
|
-- 7476, B4, flip flop 1 --
|
|
-- dual master slave jk flip flop with clear --
|
|
-- pin 1 clk 1 --
|
|
-- pin 3 clr 1 --
|
|
-- pin 14 qn --
|
|
-- pin 15 q --
|
|
-- --
|
|
-- Overall B4 and C4(pin 6-12) --
|
|
-- Creates the frequency pulse trains that are the basis for the timing --
|
|
-- of explosion and collision events (such as rocket spinning, screen --
|
|
-- inversing/"flashing", explosion sound and removing saucer/rocket from --
|
|
-- the screen for a while after being hit ) --
|
|
-----------------------------------------------------------------------------
|
|
b4_1 <= d4_6; -- explosion clock
|
|
b4_3 <= a4_12; -- clrn
|
|
|
|
process (super_clk, b4_3)
|
|
begin
|
|
if b4_3 = '0' then -- clr active low
|
|
b4_15 <= '0';
|
|
b4_1_old <= '0';
|
|
elsif rising_edge (super_clk) then
|
|
b4_1_old <= b4_1;
|
|
if (b4_1_old = '1') and (b4_1 = '0') then
|
|
-- data out on falling edge; j,k can be viewed as permanent high => toggle
|
|
b4_15 <= not b4_15;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Frequency divider logic flipflop 2 --
|
|
-- 7476, B4, flip flop 2 --
|
|
-- dual master slave jk flip flop with clear --
|
|
-- pin 6 clk 1 --
|
|
-- pin 8 clr 1 --
|
|
-- pin 10 qn --
|
|
-- pin 11 q --
|
|
-- --
|
|
-- Overall B4 and C4(pin 6-12) --
|
|
-- Creates the frequency pulse trains that are the basis for the timing --
|
|
-- of explosion and collision events (such as rocket spinning, screen --
|
|
-- inversing/"flashing", explosion sound and removing saucer/rocket from --
|
|
-- the screen for a while after being hit ) --
|
|
-----------------------------------------------------------------------------
|
|
b4_6 <= b4_15; -- clk
|
|
b4_8 <= a4_12; --clrn
|
|
|
|
process (super_clk, b4_8)
|
|
begin
|
|
if b4_8 = '0' then
|
|
b4_11 <= '0';
|
|
b4_10 <= '1';
|
|
b4_6_old <= '0';
|
|
elsif rising_edge (super_clk) then
|
|
b4_6_old <= b4_6;
|
|
if (b4_6_old = '1') and (b4_6 = '0') then
|
|
-- data out on falling edge, j,k are permanent high => toggle
|
|
b4_11 <= not b4_11;
|
|
b4_10 <= not b4_10;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Frequency divider logic flipflop 3 --
|
|
-- 7476, B4, flip flop 3 --
|
|
-- dual master slave jk flip flop with clear --
|
|
-- pin 6 clk 1 --
|
|
-- pin 8 clr 1 --
|
|
-- pin 10 qn --
|
|
-- pin 11 q --
|
|
-- --
|
|
-- Overall B4 and C4(pin 6-12) --
|
|
-- Creates the frequency pulse trains that are the basis for the timing --
|
|
-- of explosion and collision events (such as rocket spinning, screen --
|
|
-- inversing/"flashing", explosion sound and removing saucer/rocket from --
|
|
-- the screen for a while after being hit ) --
|
|
-----------------------------------------------------------------------------
|
|
c4_6 <= b4_11; -- clk
|
|
c4_8 <= a4_12; -- clrn
|
|
|
|
process (super_clk, c4_8)
|
|
begin
|
|
if c4_8 ='0' then
|
|
c4_11 <= '0';
|
|
c4_10 <= '1';
|
|
c4_6_old <= '0';
|
|
elsif rising_edge (super_clk) then
|
|
c4_6_old <= c4_6;
|
|
if (c4_6_old = '1') and (c4_6 = '0') then
|
|
-- data out on falling edge; j,k are permanent high => toggle
|
|
c4_11 <= not c4_11;
|
|
c4_10 <= not c4_10;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Collision and Explosion Timer --
|
|
-- is active for the duration of the rocket spin, the time the rocket --
|
|
-- and/or saucer is not visible on the screen following collision or hit --
|
|
-----------------------------------------------------------------------------
|
|
a4_8 <= not (b4_15 and b4_11 and c4_11);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: screen flash & sound timer --
|
|
-- is active for the duration of screen flash (inverse the screen color) --
|
|
-----------------------------------------------------------------------------
|
|
a4_6 <= not (b4_15 and b4_10 and c4_10);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- COLLISION DETECTION & EXPLOSION: Trigger explosion sound --
|
|
-----------------------------------------------------------------------------
|
|
d4_8 <= not a4_6; -- inversing signal to fit sound unit's active level
|
|
SB_L <= d4_8;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Hyperspace Screen Management --
|
|
-- Signals to video out unit to use inverse video signals (white becomes --
|
|
-- black and black becomes white) --
|
|
-- Inversing happens either when game is in hyperspace mode (replay) or --
|
|
-- when a collision or missile hit has occurred --
|
|
-----------------------------------------------------------------------------
|
|
j1_6 <= d5_6 xor a4_6; -- normal/hyperspace (nor/hyp)
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- GAME TIME CLOCK --
|
|
-- provide clk input to the time keeping circuit --
|
|
-----------------------------------------------------------------------------
|
|
c5_6 <= seconds_clk nand d5_9; -- seconds_clk is called "Game Speed
|
|
-- Adjust" in the original schematics
|
|
-- essentially the speed with which each
|
|
-- time unit progresses
|
|
-- d5_9 is active high when a game is "on"
|
|
-- and lets c5_6 pass through clock pulses
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- SCORE & TIME KEEPING CIRCUITRY: Keep and update time unit --
|
|
-- E3, 7490 --
|
|
-- decade counter TIME UNIT --
|
|
-----------------------------------------------------------------------------
|
|
e3_14 <= c5_6; -- clk a
|
|
e3_2 <= e5_8; -- reseet when high
|
|
|
|
process (super_clk, e3_2)
|
|
begin
|
|
if e3_2 = '1' then --- reset
|
|
e3_count <= "0000";
|
|
elsif rising_edge (super_clk) then
|
|
e3_14_old <= e3_14;
|
|
if (e3_14_old = '1') and (e3_14 = '0') then -- falling edge
|
|
if e3_count = "1001" then -- decade counter, reset after reaching 9
|
|
e3_count <= "0000";
|
|
else
|
|
e3_count <= e3_count+1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
e3_12 <= e3_count (0); -- qa
|
|
e3_11 <= e3_count (3); -- qd
|
|
e3_9 <= e3_count (1); -- qb
|
|
e3_8 <= e3_count (2); -- qc
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- SCORE & TIME KEEPING CIRCUITRY: Keep and update time tens --
|
|
-- D3, 7490 --
|
|
-- decade counter TIME TENS --
|
|
-----------------------------------------------------------------------------
|
|
d3_14 <= e3_11; -- clk a
|
|
d3_2 <= e5_8; -- reseet when high
|
|
|
|
process (super_clk, d3_2)
|
|
begin
|
|
if d3_2 = '1' then --- reset
|
|
d3_count <= "0000";
|
|
elsif rising_edge (super_clk) then
|
|
d3_14_old <= d3_14;
|
|
if (d3_14_old = '1') and (d3_14 = '0') then -- falling edge
|
|
if d3_count = "1001" then -- decade counter, reset after reaching 9
|
|
d3_count <= "0000";
|
|
else
|
|
d3_count <= d3_count+1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
d3_12 <= d3_count (0); -- qa
|
|
d3_11 <= d3_count (3); -- qd
|
|
d3_9 <= d3_count (1); -- qb
|
|
d3_8 <= d3_count (2); -- qc
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- SCORE & TIME KEEPING CIRCUITRY: keep and update rocket score --
|
|
-- C3, 7493 --
|
|
-- BINARY COUNTER --
|
|
-- interestingly they use a binary counter instead of decade --
|
|
-- which results in "strange" symbols when rocket score goes beyond 9 --
|
|
-----------------------------------------------------------------------------
|
|
c3_14 <= b5_6; -- clk a, when rocket missile hits saucer
|
|
c3_2 <= e5_8; -- reset when high
|
|
|
|
process (super_clk, c3_2)
|
|
begin
|
|
if c3_2 = '1' then --- reset
|
|
c3_count <= "0000";
|
|
elsif rising_edge (super_clk) then
|
|
c3_14_old <= c3_14;
|
|
if (c3_14_old = '1') and (c3_14 = '0') then -- falling edge
|
|
if c3_count = "1111" then -- binary counter, reset after reaching 15
|
|
c3_count <= "0000";
|
|
else
|
|
c3_count <= c3_count+1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
c3_12 <= c3_count (0); -- qa
|
|
c3_11 <= c3_count (3); -- qd
|
|
c3_9 <= c3_count (1); -- qb
|
|
c3_8 <= C3_count (2); -- qc
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- SCORE & TIME KEEPING CIRCUITRY: Keep and update saucer score --
|
|
-- B3, 7490 --
|
|
-- decade counter --
|
|
-----------------------------------------------------------------------------
|
|
b3_14 <= a5_6; -- clk a, when saucer missile hits rocket
|
|
b3_2 <= e5_8; -- reseet when high
|
|
|
|
process (super_clk, b3_2)
|
|
begin
|
|
if b3_2 = '1' then --- reset
|
|
b3_count <= "0000";
|
|
elsif rising_edge (super_clk) then
|
|
b3_14_old <= b3_14;
|
|
if (b3_14_old = '1') and (b3_14 = '0') then -- falling edge
|
|
if b3_count = "1001" then -- decade counter, reset after reaching 9
|
|
b3_count <= "0000";
|
|
else
|
|
b3_count <= b3_count+1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
b3_12 <= b3_count (0); -- qa
|
|
b3_11 <= b3_count (3); -- qd
|
|
b3_9 <= b3_count (1); -- qb
|
|
b3_8 <= b3_count (2); -- qc
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: TENS and Rocket Flag --
|
|
-- This flag is a bit clever as it embeds the input from two unrelated --
|
|
-- "items": --
|
|
-- 1) TENS - signal whether the TV beam is within the TENS horizontal --
|
|
-- position --
|
|
-- 2) Rocket - signal whether the TV beam is within the rocket score's --
|
|
-- horizontal and vertical position --
|
|
-- --
|
|
-- The "dual-info" flag is decomposed in downstream logic to determine --
|
|
-- whether to forward TIME TENS or UNITS value to the segment decoder --
|
|
-- if TIME is to be displayed OR whether to forward the rocket's or the --
|
|
-- saucer's score value to the segment decoder if TIME is not to be --
|
|
-- displayed --
|
|
-----------------------------------------------------------------------------
|
|
h1_6 <= e2_6 nand g2_8;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Select score and time(tens/unit) to display --
|
|
-- A3, 74153 --
|
|
-- DUAL 4-LINE TO 1-LINE DATA SELECTOR/MULTIPLEXOR --
|
|
-- (a,b) => output (y1 and y2) --
|
|
-- (0,0) => c0 --
|
|
-- (0,1) => c1 --
|
|
-- (1,0) => c2 --
|
|
-- (1,1) => c3 --
|
|
-- Depending on the current screen position, the two Selectors A3 and F3 --
|
|
-- forwards the corresponding value from either rocket score, --
|
|
-- saucer score, time tens or time unit to the binary-segment decoder. --
|
|
-- A3 and F3 manages four bits in total, two bits each, from the score and --
|
|
-- time tens/units - as each value has four bits. --
|
|
-- --
|
|
-- A3 forwards bit 0 and bit 1 from rocket/saucer/time unit/time tens --
|
|
-- F3 fowards bit 2 and bit 3 from rocket/saucer/time unit/time tens --
|
|
-- --
|
|
-- When Time Display is enabled (f2_6: active low) then the data --
|
|
-- selector forwards c1 or c2 (tens or units). If TENS flag is set (e2_6 --
|
|
-- cleverly embedded in h1_6) then c1(tens) is selected, otherwise unit. --
|
|
-- --
|
|
-- When Time Display is not enabled --
|
|
-- either c2 or c3 (rocket score or saucer score) are in scope; which one --
|
|
-- depends on whether Rocket Score Display is enabled (g2_8 cleverly --
|
|
-- embedded in h1_6) or not. --
|
|
-----------------------------------------------------------------------------
|
|
a3_3 <= b3_9; -- 1c3: saucer score bit qb
|
|
a3_4 <= c3_9; -- 1c2: rocket score bit qb
|
|
a3_5 <= d3_9; -- 1c1: time tens bit qb
|
|
a3_6 <= e3_9; -- 1c0: time units bit qb
|
|
|
|
a3_10 <= e3_12; -- 2c0: time units bit qa
|
|
a3_11 <= d3_12; -- 2c1: time tens bit qa
|
|
a3_12 <= c3_12; -- 2c2: rocket score bit qa
|
|
a3_13 <= b3_12; -- 2c3: saucer score bit qa
|
|
|
|
a3_14 <= h1_6; -- a select
|
|
a3_2 <= f2_6; -- b select
|
|
|
|
a3_7 <= -- y1
|
|
a3_6 when (a3_14 = '0' and a3_2 = '0') else
|
|
a3_5 when (a3_14 = '1' and a3_2 = '0') else
|
|
a3_4 when (a3_14 = '0' and a3_2 = '1') else
|
|
a3_3;
|
|
|
|
|
|
a3_9 <= -- y2
|
|
a3_10 when (a3_14 = '0' and a3_2 = '0') else
|
|
a3_11 when (a3_14 = '1' and a3_2 = '0') else
|
|
a3_12 when (a3_14 = '0' and a3_2 = '1') else
|
|
a3_13;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DISPLAY SCORE & TIME: Select score and time (tens/unit) to display --
|
|
-- F3, 74153 --
|
|
-- DUAL 4-LINE TO 1-LINE DATA SELECTOR/MULTIPLEXOR --
|
|
-- (a,b) => output (y1 and y2) --
|
|
-- (0,0) => c0 --
|
|
-- (0,1) => c1 --
|
|
-- (1,0) => c2 --
|
|
-- (1,1) => c3 --
|
|
-- Depending on the current screen position, the two Selectors A3 and F3 --
|
|
-- forwards the corresponding value from either rocket score, --
|
|
-- saucer score, time tens or time unit to the binary-segment decoder. --
|
|
-- A3 and F3 manages four bits in total, two bits each, from the score and --
|
|
-- time tens/units - as each value has four bits. --
|
|
-- --
|
|
-- A3 forwards bit 0 and bit 1 from rocket/saucer/time unit/time tens --
|
|
-- F3 fowards bit 2 and bit 3 from rocket/saucer/time unit/time tens --
|
|
-- --
|
|
-- When Time Display is enabled (f2_6: active low) then the data --
|
|
-- selector forwards c1 or c2 (tens or units). If TENS flag is set (e2_6 --
|
|
-- cleverly embedded in h1_6) then c1(tens) is selected, otherwise unit. --
|
|
-- --
|
|
-- When Time Display is not enabled --
|
|
-- either c2 or c3 (rocket score or saucer score) are in scope; which one --
|
|
-- depends on whether Rocket Score Display is enabled (g2_8 cleverly --
|
|
-- embedded in h1_6) or not. --
|
|
-----------------------------------------------------------------------------
|
|
f3_3 <= b3_11; -- 1c3: saucer score bit qd
|
|
f3_4 <= c3_11; -- 1c2: rocket score bit qd
|
|
f3_5 <= d3_11; -- 1c1: time tens bit qd
|
|
f3_6 <= e3_11; -- 1c0: time units bit qd
|
|
|
|
f3_10 <= e3_8; -- 2c0: time units bit qc
|
|
f3_11 <= d3_8; -- 2c1: time tens bit qc
|
|
f3_12 <= c3_8; -- 2c2: rocket score bit qc
|
|
f3_13 <= b3_8; -- 2c3: saucer score bit qc
|
|
|
|
f3_14 <= h1_6; -- a select
|
|
f3_2 <= f2_6; -- b select
|
|
|
|
f3_7 <= -- y1
|
|
f3_6 when (f3_14 = '0' and f3_2 = '0') else
|
|
f3_5 when (f3_14 = '1' and f3_2 = '0') else
|
|
f3_4 when (f3_14 = '0' and f3_2 = '1') else
|
|
f3_3;
|
|
|
|
f3_9 <= -- y2
|
|
f3_10 when (f3_14 = '0' and f3_2 = '0') else
|
|
f3_11 when (f3_14 = '1' and f3_2 = '0') else
|
|
f3_12 when (f3_14 = '0' and f3_2 = '1') else
|
|
f3_13;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- REPLAY CIRCUITRY: Compare Player/Rocket score with Saucer score --
|
|
-- A2, 9324 --
|
|
-- 5-Bit comparator --
|
|
-- comparing score between rocket and saucer --
|
|
-- if player/rocket score is higher than saucer score then set a2_15 flag --
|
|
-----------------------------------------------------------------------------
|
|
a2_3 <= b3_12;
|
|
a2_4 <= b3_9;
|
|
a2_5 <= b3_8;
|
|
a2_6 <= b3_11;
|
|
|
|
a2_10 <= c3_11;
|
|
a2_11 <= c3_8;
|
|
a2_12 <= c3_9;
|
|
a2_13 <= c3_12;
|
|
|
|
a2_A (0) <= a2_13;
|
|
a2_A (1) <= a2_12;
|
|
a2_A (2) <= a2_11;
|
|
a2_A (3) <= a2_10;
|
|
|
|
a2_B (0) <= a2_3;
|
|
a2_B (1) <= a2_4;
|
|
a2_B (2) <= a2_5;
|
|
a2_B (3) <= a2_6;
|
|
|
|
-- checks if rocket score is higher than saucer score
|
|
a2_15 <= '1' when a2_A > a2_B else '0';
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- REPLAY CIRCUITRY: Set Replay or not --
|
|
-- --
|
|
-- SB_F connected to switch allows for replay --
|
|
-----------------------------------------------------------------------------
|
|
c2_11 <= SB_F and a2_15; -- determine replay or not, depending on score
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Coin Latch
|
|
--
|
|
-- A tricky latch constructed with relay and transistor(Q13).
|
|
--
|
|
-- The actual output is active low but it is only used via inverter e5_12,
|
|
-- at last it turns active high.
|
|
--
|
|
-- Note: This digital reproduction directly outputs inverted e5_12 signal.
|
|
--
|
|
-- e5_12 determines whether or not the game can be started
|
|
-- when the start button is pressed via RS flip-flop(d6_8).
|
|
--
|
|
-- Also it is used to keep reset the following two D-FFs until a coin inserted.
|
|
-- d5_6(Replay Flag)
|
|
-- d5_9(Game On/Off Flag)
|
|
--
|
|
--
|
|
-- Transition of actual output (and e5_12):
|
|
--
|
|
-- < Initial state: High (e5_12: Low) >
|
|
-- Because CoinSwitchNO is open(or VCC), there is no current through relay.
|
|
-- So relay is open, resulting output keeping high.
|
|
--
|
|
-- < Transition to Low (e5_12: High) >
|
|
-- Once a coin inserted(that is, CoinSwitchNO falls GND), relay turns on (closes).
|
|
-- Transistor(Q13) is always conducted state to GND except latch clear signal(c5_3)
|
|
-- is turns low at the end of the game.
|
|
-- Therefore, when relay closes, the latch output stuck GND via Q13,
|
|
-- even though CoinSwitchNO is back to high.
|
|
--
|
|
-- < Transition to High (e5_12: Low) >
|
|
-- When the game is over, latch clear signal(c5_3) turns low,
|
|
-- resulting transistor(Q13) to be non-conducting state.
|
|
-- Then CoinSwitchNO turns high, relay turns off(opens),
|
|
-- and the latch output keeps high after that.
|
|
--
|
|
--
|
|
-- SB_C connected to coin microswitch
|
|
-- e5_12 is inverted latch output
|
|
-----------------------------------------------------------------------------
|
|
process (super_clk, reset)
|
|
begin
|
|
if reset = '1' then
|
|
e5_12 <= '0';
|
|
elsif rising_edge (super_clk) then
|
|
if SB_C = '1' then
|
|
e5_12 <= '1';
|
|
elsif c5_3 = '0' then
|
|
e5_12 <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Coin Latch Clear
|
|
--
|
|
-- 1. C6(74121 monostable multivibrator) outputs about 280,000 ns pulse -
|
|
-- triggered by rising edge of c6_5 (game end)
|
|
--
|
|
-- 2. A5(7474 D-FF) outputs
|
|
-- * 2playpercoin sw is off
|
|
-- always high
|
|
-- * 2playpercoin sw is on
|
|
-- alternate high and low changing at the end of each game end
|
|
--
|
|
-- 3. C5_3(NAND gates) outputs
|
|
-- * 2playpercoin sw is off
|
|
-- coin latch clear pulse(active low) at every game end
|
|
-- * 2playpercoin sw is on
|
|
-- coin latch clear pulse(active low) once every two times at game end
|
|
--
|
|
-- SB_D connected to 2 Play per coin SW
|
|
-- c5_3 is coin latch clear signal (active low)
|
|
-----------------------------------------------------------------------------
|
|
C6_74121 : process (super_clk, reset)
|
|
type t_state is (IDLE, COUNT);
|
|
variable state : t_state := IDLE;
|
|
constant cnt_end : integer range 0 to 16383 := 14000; -- 280,000 ns / 20 ns
|
|
variable cnt : integer range 0 to 16383;
|
|
begin
|
|
if reset = '1' then
|
|
c6_6 <= '0';
|
|
c6_1 <= '1';
|
|
state := IDLE;
|
|
cnt := 0;
|
|
elsif rising_edge (super_clk) then
|
|
c6_5_old <= c6_5;
|
|
case state is
|
|
when IDLE =>
|
|
c6_6 <= '0';
|
|
c6_1 <= '1';
|
|
if (c6_5_old = '0' and c6_5 = '1') then
|
|
state := COUNT;
|
|
cnt := 0;
|
|
end if;
|
|
when COUNT =>
|
|
c6_6 <= '1';
|
|
c6_1 <= '0';
|
|
cnt := cnt + 1;
|
|
if (cnt = cnt_end) then
|
|
state := IDLE;
|
|
end if;
|
|
when others =>
|
|
state := IDLE;
|
|
end case;
|
|
end if;
|
|
end process;
|
|
|
|
A5_7474 : process (super_clk, reset, SB_D)
|
|
begin
|
|
if reset = '1' then
|
|
a5_9 <= '0';
|
|
elsif SB_D = '0' then
|
|
a5_9 <= '1';
|
|
elsif rising_edge (super_clk) then
|
|
c6_1_old <= c6_1;
|
|
if (c6_1_old = '0' and c6_1 = '1') then
|
|
a5_9 <= not(a5_9);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
c5_3 <= not(c6_6 and a5_9);
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Start Button Latch
|
|
--
|
|
-- RS-FF made of 4-Input NAND to make start game pulse(active low)
|
|
--
|
|
-- Outputs low while start button is pressed, otherwise outputs high.
|
|
--
|
|
-- Pressing start button is ignored in the following conditions
|
|
-- * Coin latch output (e5_12) is low, which means no credit
|
|
-- * Inverted game on/off flag(d5_8) is low, which means game has already started
|
|
--
|
|
-- SB_7 connected to Start button on player control panel.
|
|
-- d6_8 outputs game start pulse(active low)
|
|
-----------------------------------------------------------------------------
|
|
process (SB_7, e5_12, d5_8) begin
|
|
if (SB_7 = '1' and e5_12 = '1' and d5_8 = '1') then
|
|
d6_8 <= '0';
|
|
else
|
|
d6_8 <= '1';
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Replay or not --
|
|
-- will signal for replay if player score is greater than saucer score --
|
|
-- (c2_11) and if player is not already in replay mode (d5_6) --
|
|
-----------------------------------------------------------------------------
|
|
c2_8 <= c2_11 and d5_6;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Signal that Time = 99 --
|
|
-- signals that game time has reached 99 --
|
|
-- downstream logic will determine whether to stop the game or go for --
|
|
-- replay --
|
|
-----------------------------------------------------------------------------
|
|
e5_10 <= not d3_11;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Replay Flag --
|
|
-- D5, 7474, pin 1-6 --
|
|
-- d5_6 signals whether game is in replay mode or not --
|
|
-----------------------------------------------------------------------------
|
|
d5_1 <= e5_12; -- clrn
|
|
d5_3 <= e5_10; -- clk
|
|
d5_2 <= c2_8; -- d : replay or not
|
|
|
|
process(super_clk, d5_1)
|
|
begin
|
|
if d5_1 = '0' then
|
|
d5_6 <= '1'; -- qn is cleared when clrn is active low
|
|
elsif rising_edge (super_clk) then
|
|
d5_3_old <= d5_3;
|
|
if (d5_3_old = '0') and (d5_3 = '1') then
|
|
d5_6 <= not d5_2;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Game On/Off Flag --
|
|
-- D5, 7474, pin 8-13 --
|
|
-- d5_9 signals whether game is on or off, 1-on, 0-off --
|
|
-- d5_8 is the inverse of d5_9 --
|
|
-----------------------------------------------------------------------------
|
|
d5_13 <= e5_12; -- clrn
|
|
d5_11 <= e5_10; -- clk
|
|
d5_12 <= c2_8; -- d
|
|
d5_10 <= d6_8; -- pren
|
|
|
|
process(super_clk, d5_13, d5_10)
|
|
begin
|
|
if d5_13 = '0' then
|
|
d5_9 <= '0'; -- q is cleared when clrn is active low
|
|
d5_8 <= '1'; -- qn is cleared when clrn is active low
|
|
elsif d5_10 = '0' then
|
|
d5_9 <= '1'; -- q is set to high when pren is active low
|
|
d5_8 <= '0'; -- qn is set to low when pren is active low
|
|
elsif rising_edge (super_clk) then
|
|
d5_11_old <= d5_11;
|
|
if (d5_11_old = '0') and (d5_11 = '1') then
|
|
d5_9 <= d5_12;
|
|
d5_8 <= not d5_12;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
c6_5 <= d5_8;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Reset Score and Time (Unit and Tens) --
|
|
-- signals to score and time keeping units to reset score and time --
|
|
-----------------------------------------------------------------------------
|
|
e5_8 <= not d6_8;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- START/END GAME: Audio On/Off --
|
|
-- signals to audio unit to switch on the sound, incl backgrund noise, --
|
|
-- when a game is playing, otherwise switch off --
|
|
-----------------------------------------------------------------------------
|
|
SB_K <= d5_8; -- audio gate signal
|
|
|
|
end sync_star_board_architecture; |