1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-04-20 08:46:28 +00:00
Files
Gehstock.Mist_FPGA/Arcade_MiST/Ladybug Hardware/LadyBug_MiST/rtl/ladybug_sprite.vhd
2018-02-07 23:24:44 +01:00

858 lines
25 KiB
VHDL

-------------------------------------------------------------------------------
--
-- FPGA Lady Bug
--
-- $Id: ladybug_sprite.vhd,v 1.12 2005/10/10 22:02:14 arnim Exp $
--
-- Sprite Video Module of Lady Bug Machine.
--
-- This unit contains the whole sprite logic which is distributed on the
-- CPU and video boards.
--
-------------------------------------------------------------------------------
--
-- Copyright (c) 2005, Arnim Laeuger (arnim.laeuger@gmx.net)
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- Redistributions of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.
--
-- Redistributions in synthesized form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
--
-- Neither the name of the author nor the names of other contributors may
-- be used to endorse or promote products derived from this software without
-- specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--
-- Please report bugs to the author, but before you do so, please
-- make sure that this is not a derivative work and that
-- you have the latest version of this file.
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ladybug_sprite is
port (
-- Clock and Reset Interface ----------------------------------------------
clk_20mhz_i : in std_logic;
por_n_i : in std_logic;
res_n_i : in std_logic;
clk_en_10mhz_i : in std_logic;
clk_en_10mhz_n_i : in std_logic;
clk_en_5mhz_i : in std_logic;
clk_en_5mhz_n_i : in std_logic;
-- CPU Interface ----------------------------------------------------------
cs7_n_i : in std_logic;
a_i : in std_logic_vector( 9 downto 0);
d_from_cpu_i : in std_logic_vector( 7 downto 0);
-- RGB Video Interface ----------------------------------------------------
h_i : in std_logic_vector( 3 downto 0);
h_t_i : in std_logic_vector( 3 downto 0);
hx_i : in std_logic;
ha_d_i : in std_logic;
v_i : in std_logic_vector( 3 downto 0);
v_t_i : in std_logic_vector( 3 downto 0);
vbl_n_i : in std_logic;
vbl_d_n_i : in std_logic;
vc_d_i : in std_logic;
blank_flont_i : in std_logic;
blank_i : in std_logic;
sig_o : out std_logic_vector( 4 downto 1);
-- Sprite ROM Interface ---------------------------------------------------
rom_sprite_a_o : out std_logic_vector(11 downto 0);
rom_sprite_d_i : in std_logic_vector(15 downto 0)
);
end ladybug_sprite;
architecture rtl of ladybug_sprite is
signal sprite_ram_cs_n_s,
sprite_ram_we_n_s,
clk_5mhz_n_q,
clk_en_eck_s,
clk_en_rd_s,
clk_en_5ck_n_s,
clk_en_6ck_n_s,
clk_en_7ck_n_s,
clk_en_b7_p3_s,
clk_en_e7_3_s,
s6ck_n_s,
s7ck_n_s,
e5_p8_s,
a8_p5_n_s,
ct0_s,
ct1_s,
cr_mux_sel_s,
ck_inh_s,
ck_inh_n_q,
qh1_s,
qh2_s : std_logic;
signal rb_s,
rb_unflip_s,
rc_s : std_logic_vector( 7 downto 0);
signal c_s : std_logic_vector(10 downto 0);
signal v_cnt_s : std_logic_vector( 4 downto 0);
signal ra_s : std_logic_vector( 9 downto 0);
signal ma_s : std_logic_vector(11 downto 0);
signal ma_q : std_logic_vector(11 downto 6);
signal mb_q : std_logic_vector( 1 downto 0);
signal mc_q : std_logic_vector( 6 downto 0);
signal cl_q : std_logic_vector( 4 downto 0);
signal j7_s : std_logic_vector( 2 downto 0);
signal df_muxed_s : std_logic_vector( 7 downto 0);
signal lu_a_s : std_logic_vector( 4 downto 0);
signal lu_d_s : std_logic_vector( 7 downto 0);
signal lu_d_mux_s : std_logic_vector( 3 downto 0);
signal rd_shift_s,
rd_shift_int,
rd_vram_s : std_logic_vector(15 downto 0);
signal rs_s,
rs_int,
rs_n_s : std_logic_vector( 3 downto 0);
signal rs_enable_s : std_logic;
signal shift_oc_n_s : std_logic;
signal j6_shifter : std_logic_vector( 3 downto 0);
signal h6_shifter : std_logic_vector( 3 downto 0);
signal ctrl_lu_a_s : std_logic_vector( 4 downto 0);
signal ctrl_lu_d_s : std_logic_vector( 7 downto 0);
signal v_cnt_a5_a6_s : std_logic_vector( 7 downto 0);
signal ctrl_lu_q_d_s,
ctrl_lu_q : std_logic_vector( 6 downto 1);
signal vram_we_n_s : std_logic;
signal vram_a6_in_s,
vram_a6_out_s,
vram_b6_in_s,
vram_b6_out_s,
vram_c6_in_s,
vram_c6_out_s,
vram_d6_in_s,
vram_d6_out_s : std_logic_vector( 3 downto 0);
signal ca_q : std_logic_vector( 3 downto 1);
signal ca6_s,
ca7_s,
ca8_s : std_logic;
signal x_s : std_logic_vector( 5 downto 0);
signal cr_s : std_logic_vector( 9 downto 0);
signal vram_q : std_logic_vector(15 downto 0);
begin
-----------------------------------------------------------------------------
-- The Vertical Counters C5 D5
-----------------------------------------------------------------------------
v_cnt_c5_c6_b : process(clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
v_cnt_s <= (others=>'0');
elsif rising_edge(clk_20mhz_i) then
if clk_en_b7_p3_s = '1' then
if e5_p8_s = '0' then
v_cnt_s <= (v_t_i & "0");
else
v_cnt_s <= v_cnt_s + 1;
end if;
end if;
end if;
end process;
-----------------------------------------------------------------------------
-- Counter J7
-----------------------------------------------------------------------------
j7_b : process(clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
j7_s <= (others=>'0');
elsif rising_edge(clk_20mhz_i) then
if clk_en_10mhz_i = '1' then
if s6ck_n_s = '0' then
j7_s <= not mc_q(6) & mc_q(6) & '0';
elsif (ct0_s or ct1_s or a8_p5_n_s or ck_inh_s) = '0' then
j7_s <= j7_s + 1;
end if;
end if;
end if;
end process;
-----------------------------------------------------------------------------
-- Sprite VRAM Counters A5 A6
-----------------------------------------------------------------------------
ct0_s <= v_cnt_a5_a6_s(0);
ct1_s <= v_cnt_a5_a6_s(1);
x_s <= v_cnt_a5_a6_s(7 downto 2);
v_cnt_a5_a6_b : process(clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
v_cnt_a5_a6_s <= (others=>'0');
elsif rising_edge(clk_20mhz_i) then
if clk_en_10mhz_i = '1' then
if s7ck_n_s = '0' then
v_cnt_a5_a6_s(7 downto 4) <= (rb_s(7 downto 4));
v_cnt_a5_a6_s(3 downto 0) <= (rb_s(3 downto 2) & not rc_s(7) & not rc_s(6));
elsif ck_inh_n_q = '1' then
v_cnt_a5_a6_s <=v_cnt_a5_a6_s + 1;
end if;
end if;
end if;
end process;
-----------------------------------------------------------------------------
-- Process sprite_ram_ctrl
--
-- Purpose:
-- Generates the control signals for the sprite RAM.
--
sprite_ram_ctrl: process ( cs7_n_i,
vbl_n_i,
a_i,
c_s, v_cnt_s)
variable cpu_access_v : std_logic;
begin
cpu_access_v := not cs7_n_i and not vbl_n_i;
sprite_ram_we_n_s <= not cpu_access_v;
sprite_ram_cs_n_s <= cpu_access_v nor vbl_n_i;
if vbl_n_i = '0' then
ra_s <= a_i;
else
ra_s <= v_cnt_s(4 downto 0) & c_s(4 downto 0);
end if;
end process sprite_ram_ctrl;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- The Sprite RAM P5 N5
-----------------------------------------------------------------------------
sprite_ram_b : entity work.ladybug_sprite_ram
port map (
clk_i => clk_20mhz_i,
clk_en_i => clk_en_5mhz_i,
a_i => ra_s,
cs_n_i => sprite_ram_cs_n_s,
we_n_i => sprite_ram_we_n_s,
d_i => d_from_cpu_i,
d_o => rb_s
);
-----------------------------------------------------------------------------
-- Process rc_add
--
-- Purpose:
-- Implements IC N6 and E6 which add sprite RAM data and Cx signals to
-- form RCx bus.
--
rc_add: process (rb_s, c_s, v_i)
variable a_v, b_v,
sum_v : std_logic_vector(7 downto 0);
begin
-- prepare the inputs of the adder
a_v(3 downto 0) := rb_s(3 downto 0);
a_v(4) := '1';
a_v(5) := '0';
a_v(7 downto 6) := rb_s(1 downto 0);
b_v(0) := not c_s(6);
b_v(1) := not c_s(7);
b_v(2) := not c_s(8);
b_v(3) := not v_i(3);
b_v(4) := c_s(10);
b_v(5) := '0';
b_v(7 downto 6) := "11";
sum_v := a_v + b_v;
rc_s <= sum_v;
end process rc_add;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Sprite Control Logic
-----------------------------------------------------------------------------
sprite_ctrl_b : entity work.ladybug_sprite_ctrl
port map (
clk_20mhz_i => clk_20mhz_i,
clk_en_5mhz_i => clk_en_5mhz_i,
clk_en_5mhz_n_i => clk_en_5mhz_n_i,
por_n_i => por_n_i,
vbl_n_i => vbl_n_i,
vbl_d_n_i => vbl_d_n_i,
vc_i => v_i(2),
vc_d_i => vc_d_i,
ha_i => h_i(0),
ha_d_i => ha_d_i,
rb6_i => rb_s(6),
rb7_i => rb_s(7),
rc3_i => rc_s(3),
rc4_i => rc_s(4),
rc5_i => rc_s(5),
j7_b_i => j7_s(1),
j7_c_i => j7_s(2),
clk_en_eck_i => clk_en_eck_s,
c_o => c_s,
clk_en_5ck_n_o => clk_en_5ck_n_s,
clk_en_6ck_n_o => clk_en_6ck_n_s,
clk_en_7ck_n_o => clk_en_7ck_n_s,
s6ck_n_o => s6ck_n_s,
s7ck_n_o => s7ck_n_s,
clk_en_b7_p3_o => clk_en_b7_p3_s,
e5_p8_o => e5_p8_s,
clk_en_e7_3_o => clk_en_e7_3_s,
a8_p5_n_o => a8_p5_n_s
);
-----------------------------------------------------------------------------
-- Process misc_seq
--
-- Purpose:
-- Implements several sequential elements.
--
misc_seq: process (clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
clk_5mhz_n_q <= '0';
ma_q <= (others => '0');
mb_q <= (others => '0');
mc_q <= (others => '0');
cl_q <= (others => '0');
ck_inh_n_q <= '1';
elsif clk_20mhz_i'event and clk_20mhz_i = '1' then
-- Turn clk_5mhz_n into clock waveform ----------------------------------
if clk_en_5mhz_n_i = '1' then
clk_5mhz_n_q <= '1';
elsif clk_en_5mhz_i = '1' then
clk_5mhz_n_q <= '0';
end if;
-- 8-Bit Register M6 ----------------------------------------------------
if clk_en_5ck_n_s = '1' then
mb_q <= rb_s(1 downto 0);
ma_q <= rb_s(7 downto 2);
end if;
-- 8-Bit Register P6 ----------------------------------------------------
if clk_en_e7_3_s = '1' then
-- these are inverted based on mc_q(4)
mc_q(3 downto 0) <= rc_s(3 downto 0);
-- inverts sprites horizontally
mc_q(4) <= rb_s(4);
-- inverts sprites vertically
mc_q(5) <= rb_s(5);
--
mc_q(6) <= rb_s(6);
end if;
-- 6-Bit Register B6 ----------------------------------------------------
if clk_en_6ck_n_s = '1' then
cl_q <= rb_s(4 downto 0);
end if;
-- Flip-Flop H8 ---------------------------------------------------------
if clk_en_10mhz_n_i = '1' then
ck_inh_n_q <= not ck_inh_s;
end if;
end if;
end process misc_seq;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process ma_vec
--
-- Purpose:
-- Build the ma_s vector.
--
ma_vec: process ( ma_q,
mb_q,
mc_q,
j7_s)
begin
ma_s(11 downto 6) <= ma_q;
if mc_q(6) = '0' then
ma_s(5) <= mb_q(1);
ma_s(4) <= mb_q(0);
else
ma_s(5) <= mc_q(3) xor mc_q(4);
ma_s(4) <= mc_q(5) xor j7_s(2);
end if;
ma_s(3) <= mc_q(2) xor mc_q(4);
ma_s(2) <= mc_q(1) xor mc_q(4);
ma_s(1) <= mc_q(0) xor mc_q(4);
ma_s(0) <= mc_q(5) xor j7_s(0);
end process ma_vec;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process df_mux
--
-- Purpose:
-- Builds the multiplexed data from Sprite ROM.
-- Two-stage multiplexer:
-- 1) ROM data to DFx: 16->8
-- 2) DF to input for shift register: 8->8
-- This is actually a scrambler.
--
df_mux: process ( rom_sprite_d_i,
cl_q,
mc_q)
variable df_v : std_logic_vector(7 downto 0);
begin
if cl_q(4) = '0' then
-- ROM L7
df_v := rom_sprite_d_i( 7 downto 0);
else
-- ROM M7
df_v := rom_sprite_d_i(15 downto 8);
end if;
if mc_q(5) = '0' then
df_muxed_s(0) <= df_v(1);
df_muxed_s(1) <= df_v(3);
df_muxed_s(2) <= df_v(5);
df_muxed_s(3) <= df_v(7);
--
df_muxed_s(4) <= df_v(0);
df_muxed_s(5) <= df_v(2);
df_muxed_s(6) <= df_v(4);
df_muxed_s(7) <= df_v(6);
else
df_muxed_s(0) <= df_v(7);
df_muxed_s(1) <= df_v(5);
df_muxed_s(2) <= df_v(3);
df_muxed_s(3) <= df_v(1);
--
df_muxed_s(4) <= df_v(6);
df_muxed_s(5) <= df_v(4);
df_muxed_s(6) <= df_v(2);
df_muxed_s(7) <= df_v(0);
end if;
end process df_mux;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- The Two 8-Bit Shift Registers H6 J6
-----------------------------------------------------------------------------
shifters_h6_j6 : process(clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
h6_shifter <= (others=>'0');
j6_shifter <= (others=>'0');
elsif rising_edge(clk_20mhz_i) then
if (clk_en_10mhz_i and not ck_inh_s) = '1' then
if (ct0_s or ct1_s or a8_p5_n_s) = '0' then
h6_shifter <= df_muxed_s(3 downto 0);
j6_shifter <= df_muxed_s(7 downto 4);
else
h6_shifter <= h6_shifter(2 downto 0) & "0";
j6_shifter <= j6_shifter(2 downto 0) & "0";
end if;
end if;
end if;
end process;
qh1_s <= h6_shifter(3);
qh2_s <= j6_shifter(3);
-----------------------------------------------------------------------------
-- Sprite Look-up PROM F4
-----------------------------------------------------------------------------
lu_a_s(4 downto 2) <= cl_q(2 downto 0);
lu_a_s(1) <= qh2_s;
lu_a_s(0) <= qh1_s;
prom_F4 : entity work.prom_10_1
port map (
CLK => clk_20mhz_i,
ADDR => lu_a_s,
DATA => lu_d_s
);
lu_d_mux_s <= lu_d_s(3 downto 0) when cl_q(3) = '0' else lu_d_s(7 downto 4);
-----------------------------------------------------------------------------
-- Sprite Control Look-up PROM C4
-----------------------------------------------------------------------------
ctrl_lu_a_s(0) <= '1';
ctrl_lu_a_s(1) <= hx_i;
ctrl_lu_a_s(2) <= clk_5mhz_n_q;
ctrl_lu_a_s(3) <= h_i(0);
ctrl_lu_a_s(4) <= h_i(1);
prom_C4 : entity work.prom_10_3
port map (
CLK => clk_20mhz_i,
ADDR => ctrl_lu_a_s,
DATA => ctrl_lu_d_s
);
-----------------------------------------------------------------------------
-- Process ctrl_lu_seq
--
-- Purpose:
-- Registers output of Sprite Control Look-up PROM.
--
ctrl_lu_seq: process (clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
ctrl_lu_q <= (others => '0');
elsif clk_20mhz_i'event and clk_20mhz_i = '1' then
ctrl_lu_q <= ctrl_lu_q_d_s;
end if;
end process ctrl_lu_seq;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process ctrl_lu_comb
--
-- Purpose:
-- Combinational logic for the sprite control registers.
--
ctrl_lu_comb: process ( clk_en_10mhz_i,
ctrl_lu_d_s,
ctrl_lu_q,
ctrl_lu_q_d_s)
begin
-- default assignments
ctrl_lu_q_d_s <= ctrl_lu_q;
clk_en_eck_s <= '0';
clk_en_rd_s <= '0';
-- register control
if clk_en_10mhz_i = '1' then
ctrl_lu_q_d_s <= ctrl_lu_d_s(5 downto 0);
if ctrl_lu_q(1) = '0' and ctrl_lu_q_d_s(1) = '1' then
-- detect rising edge on ctrl_lu_q(1)
clk_en_eck_s <= '1';
end if;
if ctrl_lu_q(6) = '0' and ctrl_lu_q_d_s(6) = '1' then
-- detect rising edge on ctrl_lu_q(6)
clk_en_rd_s <= '1';
end if;
end if;
end process ctrl_lu_comb;
--
shift_oc_n_s <= ctrl_lu_q(1) nand res_n_i;
ck_inh_s <= ctrl_lu_q(2);
cr_mux_sel_s <= ctrl_lu_q(3);
vram_we_n_s <= ctrl_lu_q(4);
rs_enable_s <= ctrl_lu_q(5);
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process ca_seq
--
-- Purpose:
-- Implements B5, the register that holds the CS flip-flops.
--
ca_seq: process (clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
ca_q <= (others => '0');
elsif clk_20mhz_i'event and clk_20mhz_i = '1' then
if clk_en_7ck_n_s = '1' then
ca_q <= c_s(8 downto 6);
end if;
end if;
end process ca_seq;
--
ca6_s <= ca_q(1);
ca7_s <= ca_q(2);
ca8_s <= ca_q(3);
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process vram_mux
--
-- Purpose:
-- Generates the VRAM address CRx.
-- It implements chips D5, C5 and B5.
--
vram_mux: process ( h_i, h_t_i,
v_i,
x_s,
ca6_s, ca7_s, ca8_s,
cr_mux_sel_s)
begin
if cr_mux_sel_s = '0' then
-- D5
cr_s(0) <= h_i(2);
cr_s(1) <= h_i(3);
cr_s(2) <= h_t_i(0);
cr_s(3) <= h_t_i(1);
-- C5
cr_s(4) <= h_t_i(2);
cr_s(5) <= h_t_i(3);
cr_s(6) <= v_i(0);
cr_s(7) <= v_i(1);
-- B5
cr_s(8) <= v_i(2);
cr_s(9) <= v_i(3);
else
-- D5
cr_s(0) <= x_s(0);
cr_s(1) <= x_s(1);
cr_s(2) <= x_s(2);
cr_s(3) <= x_s(3);
-- C5
cr_s(4) <= x_s(4);
cr_s(5) <= x_s(5);
cr_s(6) <= ca6_s;
cr_s(7) <= ca7_s;
-- B5
cr_s(8) <= ca8_s;
cr_s(9) <= not v_i(3);
end if;
end process vram_mux;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Shift Registers
-----------------------------------------------------------------------------
shifters_a7_a8_d7_d8_f8 : process(clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
rd_shift_int <= (others=>'1');
elsif rising_edge(clk_20mhz_i) then
if (clk_en_10mhz_i and not ck_inh_s) = '1' then
rs_int <= (qh1_s nor qh2_s) & rs_int(3 downto 1);
rd_shift_int <=
lu_d_mux_s(0) & rd_shift_int(15 downto 13) &
lu_d_mux_s(1) & rd_shift_int(11 downto 9) &
lu_d_mux_s(2) & rd_shift_int( 7 downto 5) &
lu_d_mux_s(3) & rd_shift_int( 3 downto 1);
end if;
end if;
end process;
rd_shift_s <= rd_shift_int when shift_oc_n_s = '0' else (others=>'1');
rs_s <= rs_int when shift_oc_n_s = '0' else (others=>'1');
-- rs_n_s(3) <= not rs_s(3) or not rs_enable_s;
-- rs_n_s(2) <= not rs_s(2) or not rs_enable_s;
-- rs_n_s(1) <= not rs_s(1) or not rs_enable_s;
-- rs_n_s(0) <= not rs_s(0) or not rs_enable_s;
rs_n_s(3) <= rs_s(3) and rs_enable_s;
rs_n_s(2) <= rs_s(2) and rs_enable_s;
rs_n_s(1) <= rs_s(1) and rs_enable_s;
rs_n_s(0) <= rs_s(0) and rs_enable_s;
-----------------------------------------------------------------------------
-- Sprite VRAM
-----------------------------------------------------------------------------
vram_a6_in_s(0) <= rd_shift_s( 0);
vram_a6_in_s(1) <= rd_shift_s( 4);
vram_a6_in_s(2) <= rd_shift_s( 8);
vram_a6_in_s(3) <= rd_shift_s(12);
vram_a6_b : entity work.ladybug_sprite_vram
port map (
clk_i => clk_20mhz_i,
clk_en_i => '1',
a_i => cr_s,
cs_n_i => rs_n_s(0),
we_n_i => vram_we_n_s,
d_i => vram_a6_in_s,
d_o => vram_a6_out_s
);
--
vram_b6_in_s(0) <= rd_shift_s( 1);
vram_b6_in_s(1) <= rd_shift_s( 5);
vram_b6_in_s(2) <= rd_shift_s( 9);
vram_b6_in_s(3) <= rd_shift_s(13);
vram_b6_b : entity work.ladybug_sprite_vram
port map (
clk_i => clk_20mhz_i,
clk_en_i => '1',
a_i => cr_s,
cs_n_i => rs_n_s(1),
we_n_i => vram_we_n_s,
d_i => vram_b6_in_s,
d_o => vram_b6_out_s
);
--
vram_c6_in_s(0) <= rd_shift_s( 2);
vram_c6_in_s(1) <= rd_shift_s( 6);
vram_c6_in_s(2) <= rd_shift_s(10);
vram_c6_in_s(3) <= rd_shift_s(14);
vram_c6_b : entity work.ladybug_sprite_vram
port map (
clk_i => clk_20mhz_i,
clk_en_i => '1',
a_i => cr_s,
cs_n_i => rs_n_s(2),
we_n_i => vram_we_n_s,
d_i => vram_c6_in_s,
d_o => vram_c6_out_s
);
--
vram_d6_in_s(0) <= rd_shift_s( 3);
vram_d6_in_s(1) <= rd_shift_s( 7);
vram_d6_in_s(2) <= rd_shift_s(11);
vram_d6_in_s(3) <= rd_shift_s(15);
vram_d6_b : entity work.ladybug_sprite_vram
port map (
clk_i => clk_20mhz_i,
clk_en_i => '1',
a_i => cr_s,
cs_n_i => rs_n_s(3),
we_n_i => vram_we_n_s,
d_i => vram_d6_in_s,
d_o => vram_d6_out_s
);
-- Remap VRAM data outputs to the complete bus ------------------------------
rd_vram_s(15) <= vram_d6_out_s(3) or rs_n_s(3);
rd_vram_s(14) <= vram_c6_out_s(3) or rs_n_s(2);
rd_vram_s(13) <= vram_b6_out_s(3) or rs_n_s(1);
rd_vram_s(12) <= vram_a6_out_s(3) or rs_n_s(0);
--
rd_vram_s(11) <= vram_d6_out_s(2) or rs_n_s(3);
rd_vram_s(10) <= vram_c6_out_s(2) or rs_n_s(2);
rd_vram_s( 9) <= vram_b6_out_s(2) or rs_n_s(1);
rd_vram_s( 8) <= vram_a6_out_s(2) or rs_n_s(0);
--
rd_vram_s( 7) <= vram_d6_out_s(1) or rs_n_s(3);
rd_vram_s( 6) <= vram_c6_out_s(1) or rs_n_s(2);
rd_vram_s( 5) <= vram_b6_out_s(1) or rs_n_s(1);
rd_vram_s( 4) <= vram_a6_out_s(1) or rs_n_s(0);
--
rd_vram_s( 3) <= vram_d6_out_s(0) or rs_n_s(3);
rd_vram_s( 2) <= vram_c6_out_s(0) or rs_n_s(2);
rd_vram_s( 1) <= vram_b6_out_s(0) or rs_n_s(1);
rd_vram_s( 0) <= vram_a6_out_s(0) or rs_n_s(0);
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process rd_seq
--
-- Purpose:
-- Implements the registers saving the RDx bus.
--
rd_seq: process (clk_20mhz_i, por_n_i)
begin
if por_n_i = '0' then
vram_q <= (others => '0');
elsif clk_20mhz_i'event and clk_20mhz_i = '1' then
if blank_flont_i = '0' then
-- pseudo-asynchronous clear
vram_q <= (others => '0');
elsif clk_en_rd_s = '1' then
if shift_oc_n_s = '0' then
-- take data from shift registers
vram_q <= rd_shift_s;
else
-- take data from VRAM
vram_q <= rd_vram_s;
end if;
end if;
end if;
end process rd_seq;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Process sig_mux
--
-- Purpose:
-- Multiplexes the saved VRAM data to generate the four SIG outputs.
--
sig_mux: process (vram_q,
h_i,
blank_i)
variable vec_v : std_logic_vector(1 downto 0);
begin
-- default assignment
sig_o <= (others => '0');
vec_v := (h_i(1) & h_i(0));
if blank_i = '0' then
case vec_v is
when "00" =>
sig_o(1) <= vram_q( 1);
sig_o(2) <= vram_q( 5);
sig_o(3) <= vram_q( 9);
sig_o(4) <= vram_q(13);
when "01" =>
sig_o(1) <= vram_q( 2);
sig_o(2) <= vram_q( 6);
sig_o(3) <= vram_q(10);
sig_o(4) <= vram_q(14);
when "10" =>
sig_o(1) <= vram_q( 3);
sig_o(2) <= vram_q( 7);
sig_o(3) <= vram_q(11);
sig_o(4) <= vram_q(15);
when "11" =>
sig_o(1) <= vram_q( 0);
sig_o(2) <= vram_q( 4);
sig_o(3) <= vram_q( 8);
sig_o(4) <= vram_q(12);
when others =>
null;
end case;
end if;
end process sig_mux;
--
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Output Mapping
-----------------------------------------------------------------------------
rom_sprite_a_o <= ma_s;
end rtl;