1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-04-26 20:36:47 +00:00
Files
Gehstock.Mist_FPGA/Arcade_MiST/Custom Hardware/SprintOne_MiST/rtl/motion.vhd
2018-06-03 00:17:54 +02:00

382 lines
9.7 KiB
VHDL

-- Motion object generation circuitry for Kee Games Sprint 1
-- This generates the four cars which are the only moving objects in the game
-- (c) 2017 James Sweet
--
-- This 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 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.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity motion is
port(
CLK6 : in std_logic; -- 6MHz* on schematic
CLK12 : in std_logic;
PHI2 : in std_logic;
DISPLAY : in std_logic_vector(7 downto 0);
H256_s : in std_logic; -- 256H* on schematic
VCount : in std_logic_vector(7 downto 0);
HCount : in std_logic_vector(8 downto 0);
Crash_n : out std_logic;
Motor1_n : out std_logic;
Car1 : out std_logic;
Car1_n : out std_logic;
Car2 : out std_logic;
Car2_n : out std_logic;
Car3_4_n : out std_logic
);
end motion;
architecture rtl of motion is
signal phi0 : std_logic;
signal LDH1_n : std_logic;
signal LDH2_n : std_logic;
signal LDH3_n : std_logic;
signal LDH4_n : std_logic;
signal LDV1A_n : std_logic;
signal LDV2A_n : std_logic;
signal LDV3A_n : std_logic;
signal LDV4A_n : std_logic;
signal LDV1B_n : std_logic;
signal LDV2B_n : std_logic;
signal LDV3B_n : std_logic;
signal LDV4B_n : std_logic;
signal Car1_Inh : std_logic;
signal Car2_Inh : std_logic;
signal Car3_Inh : std_logic;
signal Car4_Inh : std_logic;
signal VPos_sum : std_logic_vector(7 downto 0) := x"00";
signal N4_8 : std_logic;
signal H256_n : std_logic;
signal H256 : std_logic;
signal H64 : std_logic;
signal H32 : std_logic;
signal H16 : std_logic;
signal H8 : std_logic;
signal H4 : std_logic;
signal L5_reg : std_logic_vector(3 downto 0);
signal J8_3 : std_logic;
signal J8_6 : std_logic;
signal K8_in : std_logic_vector(3 downto 0);
signal K8_out : std_logic_vector(9 downto 0);
signal P7_in : std_logic_vector(3 downto 0);
signal P7_out : std_logic_vector(9 downto 0);
signal Car1_Hpos : std_logic_vector(7 downto 0) := x"00";
signal Car2_Hpos : std_logic_vector(7 downto 0) := x"00";
signal Car3_Hpos : std_logic_vector(7 downto 0) := x"00";
signal Car4_Hpos : std_logic_vector(7 downto 0) := x"00";
signal Car1_reg : std_logic_vector(15 downto 0) := x"0000";
signal Car2_reg : std_logic_vector(15 downto 0) := x"0000";
signal Car3_reg : std_logic_vector(15 downto 0) := x"0000";
signal Car4_reg : std_logic_vector(15 downto 0) := x"0000";
signal Vid : std_logic_vector(7 downto 0);
begin
phi0 <= phi2;
H4 <= Hcount(2);
H8 <= Hcount(3);
H16 <= Hcount(4);
H32 <= Hcount(5);
H64 <= Hcount(6);
H256 <= Hcount(8);
H256_n <= not(Hcount(8));
-- Vertical line comparator
VPos_sum <= Display + VCount;
N4_8 <= not(VPos_sum(7) and VPos_sum(6) and VPos_sum(5) and VPos_sum(4) and VPos_sum(3) and H256_n and H64 and H8);
-- D type flip-flops in L5
L5: process(phi2, N4_8, VPos_sum(2 downto 0))
begin
if rising_edge(phi2) then
L5_reg <= N4_8 & VPos_sum(2 downto 0);
end if;
end process;
-- Motion object PROMs - These contain the car images for all 32 possible orientations
J6: entity work.sprom
generic map(
init_file => "rtl/roms/6399-01j6.hex",
widthad_a => 9,
width_a => 4)
port map(
clock => clk6,
address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2,
q => Vid(7 downto 4)
);
--J6: entity work.j6_prom
--port map(
-- clock => clk6,
-- address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2,
-- q => Vid(7 downto 4)
-- );
K6: entity work.sprom
generic map(
init_file => "rtl/roms/6398-01k6.hex",
widthad_a => 9,
width_a => 4)
port map(
clock => clk6,
address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2,
q => Vid(3 downto 0)
);
--K6: entity work.k6_prom
--port map(
-- clock => clk6,
-- address => Display(7 downto 3) & L5_reg(2 downto 0) & phi2,
-- q => Vid(3 downto 0)
-- );
-- Some glue logic
J8_3 <= (H4 or L5_reg(3));
J8_6 <= (H256 or H64 or H4);
-- Decoders
-- Making K8 synchronous fixes weird problem with ghost artifacts of motion objects
K8_in <= J8_3 & H32 & H16 & phi0;
K8: process(clk6, K8_in)
begin
if rising_edge(clk6) then
case K8_in is
when "0000" =>
K8_out <= "1111111110";
when "0001" =>
K8_out <= "1111111101";
when "0010" =>
K8_out <= "1111111011";
when "0011" =>
K8_out <= "1111110111";
when "0100" =>
K8_out <= "1111101111";
when "0101" =>
K8_out <= "1111011111";
when "0110" =>
K8_out <= "1110111111";
when "0111" =>
K8_out <= "1101111111";
when "1000" =>
K8_out <= "1011111111";
when "1001" =>
K8_out <= "0111111111";
when others =>
K8_out <= "1111111111";
end case;
end if;
end process;
LDV3B_n <= K8_out(7);
LDV3A_n <= K8_out(6);
LDV2B_n <= K8_out(5);
LDV2A_n <= K8_out(4);
LDV1B_n <= K8_out(3);
LDV1A_n <= K8_out(2);
LDV4B_n <= K8_out(1);
LDV4A_n <= K8_out(0);
P7_in <= J8_6 & H32 & H16 & H8;
P7: process(P7_in)
begin
case P7_in is
when "0000" =>
P7_out <= "1111111110";
when "0001" =>
P7_out <= "1111111101";
when "0010" =>
P7_out <= "1111111011";
when "0011" =>
P7_out <= "1111110111";
when "0100" =>
P7_out <= "1111101111";
when "0101" =>
P7_out <= "1111011111";
when "0110" =>
P7_out <= "1110111111";
when "0111" =>
P7_out <= "1101111111";
when "1000" =>
P7_out <= "1011111111";
when "1001" =>
P7_out <= "0111111111";
when others =>
P7_out <= "1111111111";
end case;
end process;
Crash_n <= P7_out(7);
Motor1_n <= P7_out(5);
LDH4_n <= P7_out(4);
LDH3_n <= P7_out(3);
LDH2_n <= P7_out(2);
LDH1_n <= P7_out(1);
-- Car 1 Horizontal position counter
-- This combines two 74163s at locations R5 and R6 on the PCB
R5_6: process(clk6, H256_s, LDH1_n, Display)
begin
if rising_edge(clk6) then
if LDH1_n = '0' then -- preload the counter
Car1_Hpos <= Display;
elsif H256_s = '1' then -- increment the counter
Car1_Hpos <= Car1_Hpos + '1';
end if;
if Car1_Hpos(7 downto 3) = "11111" then
Car1_Inh <= '0';
else
Car1_Inh <= '1';
end if;
end if;
end process;
-- Car 1 video shift register
-- This combines two 74165s at locations M7 and N7 on the PCB
M_N7: process(clk12, Car1_Inh, LDV1A_n, LDV1B_n, Vid)
begin
if LDV1A_n = '0' then
Car1_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register
elsif LDV1B_n = '0' then
Car1_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register
elsif rising_edge(clk12) then
if Car1_Inh = '0' then
Car1_reg <= '0' & Car1_reg(15 downto 1);
end if;
end if;
end process;
Car1 <= Car1_reg(0);
Car1_n <= not Car1_reg(0);
-- Car 2 Horizontal position counter
-- This combines two 74LS163s at locations P5 and P6 on the PCB
P5_6: process(clk6, H256_s, LDH2_n, Display)
begin
if rising_edge(clk6) then
if LDH2_n = '0' then -- preload the counter
Car2_Hpos <= Display;
elsif H256_s = '1' then -- increment the counter
Car2_Hpos <= Car2_Hpos + '1';
end if;
if Car2_Hpos(7 downto 3) = "11111" then
Car2_Inh <= '0';
else
Car2_Inh <= '1';
end if;
end if;
end process;
-- Car 2 video shift register
K_L7: process(clk12, Car2_Inh, LDV2A_n, LDV2B_n, Vid)
begin
if LDV2A_n = '0' then
Car2_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register
elsif LDV2B_n = '0' then
Car2_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register
elsif rising_edge(clk12) then
if Car2_Inh = '0' then
Car2_reg <= '0' & Car2_reg(15 downto 1);
end if;
end if;
end process;
Car2 <= Car2_reg(0);
Car2_n <= not Car2_reg(0);
-- Car 3 Horizontal position counter
-- This combines two 74LS163s at locations N5 and N6 on the PCB
N5_6: process(clk6, H256_s, LDH3_n, Display)
begin
if rising_edge(clk6) then
if LDH3_n = '0' then -- preload the counter
Car3_Hpos <= Display;
elsif H256_s = '1' then -- increment the counter
Car3_Hpos <= Car3_Hpos + '1';
end if;
if Car3_Hpos(7 downto 3) = "11111" then
Car3_Inh <= '0';
else
Car3_Inh <= '1';
end if;
end if;
end process;
-- Car 3 video shift register
H_J7: process(clk12, Car3_Inh, LDV3A_n, LDV3B_n, Vid)
begin
if LDV3A_n = '0' then
Car3_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register
elsif LDV3B_n = '0' then
Car3_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register
elsif rising_edge(clk12) then
if Car3_Inh = '0' then
Car3_reg <= '0' & Car3_reg(15 downto 1);
end if;
end if;
end process;
-- Car 4 Horizontal position counter
-- This combines two 74LS163s at locations M5 and M6 on the PCB
M5_6: process(clk6, H256_s, LDH4_n, Display)
begin
if rising_edge(clk6) then
if LDH4_n = '0' then -- preload the counter
Car4_Hpos <= Display;
elsif H256_s = '1' then -- increment the counter
Car4_Hpos <= Car4_Hpos + '1';
end if;
if Car4_Hpos(7 downto 3) = "11111" then
Car4_Inh <= '0';
else
Car4_Inh <= '1';
end if;
end if;
end process;
-- Car 4 video shift register
E_F7: process(clk12, Car4_Inh, LDV4A_n, LDV4B_n, Vid)
begin
if LDV4A_n = '0' then
Car4_reg(7 downto 0) <= Vid(7 downto 1) & '0'; -- Preload the LSB register
elsif LDV4B_n = '0' then
Car4_reg(15 downto 8) <= Vid(7 downto 0); -- Preload the MSB register
elsif rising_edge(clk12) then
if Car4_Inh = '0' then
Car4_reg <= '0' & Car4_reg(15 downto 1);
end if;
end if;
end process;
Car3_4_n <= not (Car3_reg(0) or Car4_reg(0));
end rtl;