1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-02-02 06:40:51 +00:00
Files
Gehstock.Mist_FPGA/common/IO/A6532.vhd
2024-03-01 17:08:19 +01:00

226 lines
7.1 KiB
VHDL

-- A6532 RAM-I/O-Timer (RIOT)
-- Copyright 2006, 2010 Retromaster
--
-- This file is part of A2601.
--
-- A2601 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 any later version.
--
-- A2601 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 A2601. If not, see <http://www.gnu.org/licenses/>.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ramx8 is
generic(addr_width : integer := 7);
port(clk: in std_logic;
r: in std_logic;
d_in: in std_logic_vector(7 downto 0);
d_out: out std_logic_vector(7 downto 0);
a: in std_logic_vector(addr_width - 1 downto 0));
end ramx8;
architecture arch of ramx8 is
type ram_type is array (0 to 2**addr_width - 1) of
std_logic_vector(7 downto 0);
signal ram: ram_type;
begin
process (clk, r, a)
begin
if (clk'event and clk = '1') then
if (r = '1') then
d_out <= ram(to_integer(unsigned(a)));
else
ram(to_integer(unsigned(a))) <= d_in;
end if;
end if;
end process;
end arch;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity A6532 is
port(clk: in std_logic;
ph2_en: in std_logic;
r: in std_logic;
rs: in std_logic;
cs: in std_logic;
irq: out std_logic;
d: inout std_logic_vector(7 downto 0) := "ZZZZZZZZ";
pa: inout std_logic_vector(7 downto 0);
pb: inout std_logic_vector(7 downto 0);
pa7: in std_logic;
a: in std_logic_vector(6 downto 0));
end A6532;
architecture arch of A6532 is
signal pa_reg: std_logic_vector(7 downto 0) := "00000000";
signal pb_reg: std_logic_vector(7 downto 0) := "00000000";
signal pa_ddr: std_logic_vector(7 downto 0) := "00000000";
signal pb_ddr: std_logic_vector(7 downto 0) := "00000000";
signal pa_in: std_logic_vector(7 downto 0);
signal pb_in: std_logic_vector(7 downto 0);
signal timer: std_logic_vector(7 downto 0) := "00000000";
signal timer_write: std_logic;
signal timer_read: std_logic;
signal timer_intr: std_logic := '0';
signal timer_intvl: std_logic_vector(1 downto 0) := "11";
signal timer_dvdr: std_logic_vector(10 downto 0) := "00000000001";
signal timer_inc: std_logic;
signal timer_irq_en: std_logic := '0';
signal edge_pol: std_logic := '0';
signal edge_irq_en: std_logic := '0';
signal edge_intr_lo: std_logic := '0';
signal edge_intr_hi: std_logic := '0';
signal edge_intr: std_logic;
signal intr_read: std_logic;
signal ram_d_out: std_logic_vector(7 downto 0);
signal ram_r: std_logic;
begin
io: for i in 0 to 7 generate
-- TEMPORARY FIX
pa(i) <= pa_reg(i) when pa_ddr(i) = '1' else 'Z';
pb(i) <= pb_reg(i) when pb_ddr(i) = '1' else 'Z';
--pa(i) <= 'Z';
--pb(i) <= 'Z';
pa_in(i) <= pa(i);
pb_in(i) <= pb(i) when pb_ddr(i) = '0' else pb_reg(i);
end generate;
ram: work.ramx8 port map(clk, ram_r, d, ram_d_out, a);
ram_r <= (not rs and r) or rs or not cs;
timer_write <= (not r) and rs and a(2) and a(4) and cs;
timer_read <= r and rs and a(2) and (not a(0)) and cs;
intr_read <= r and rs and a(0) and a(2) and cs;
irq <= not ((timer_intr and timer_irq_en) or (edge_intr and edge_irq_en));
edge_intr <= edge_intr_lo when edge_pol = '0' else edge_intr_hi;
process(clk, ph2_en, cs, r, rs, a, ram_d_out, pa_in, pa_ddr, pb_in, pb_ddr, timer, timer_intr, edge_intr)
begin
if r = '1' then
if (cs = '0') then
d <= "ZZZZZZZZ";
elsif rs = '0' then
d <= ram_d_out;
elsif a(2) = '0' then
case a(1 downto 0) is
when "00" =>
d <= pa_in;
when "01" =>
d <= pa_ddr;
when "10" =>
d <= pb_in;
when "11" =>
d <= pb_ddr;
when others =>
null;
end case;
elsif a(0) = '0' then
d <= timer;
elsif a(0) = '1' then
d <= timer_intr & edge_intr & "000000";
else
d <= "--------";
end if;
else
d <= "ZZZZZZZZ";
if (clk'event and clk = '1' and cs = '1' and ph2_en = '1') then
if (rs = '1') then
if a(2) = '0' then
case a(1 downto 0) is
when "00" =>
--pa_reg <= d;
when "01" =>
pa_ddr <= d;
when "10" =>
pb_reg <= d;
when "11" =>
pb_ddr <= d;
when others =>
null;
end case;
elsif a(4) = '0' then
edge_pol <= a(0);
edge_irq_en <= a(1);
end if;
end if;
end if;
end if;
end process;
process(pa7, intr_read)
begin
if (intr_read = '1') then
edge_intr_lo <= '0';
elsif (pa7'event and pa7 = '1') then
edge_intr_lo <= '1';
end if;
if (intr_read = '1') then
edge_intr_hi <= '0';
elsif (pa7'event and pa7 = '0') then
edge_intr_hi <= '1';
end if;
end process;
with timer_intvl select timer_inc <=
timer_dvdr(0) when "00",
timer_dvdr(3) when "01",
timer_dvdr(6) when "10",
timer_dvdr(10) when "11",
'-' when others;
process(clk, ph2_en)
begin
if (clk'event and clk = '1' and ph2_en = '1') then
if (timer_inc = '1') then
timer_dvdr <= "00000000001";
else
timer_dvdr <= timer_dvdr + 1;
end if;
if (timer_write = '1') then
timer <= d - 1;
timer_intvl <= a(1 downto 0);
timer_irq_en <= a(3);
timer_dvdr <= "00000000001";
elsif (timer_intr = '0') then
timer <= timer - timer_inc;
elsif (not (timer = X"00")) then
timer <= timer - 1;
end if;
if (timer = X"00" and timer_inc = '1' and timer_intr = '0' and timer_write = '0') then
timer_intr <= '1';
elsif (timer_read = '1' or timer_write = '1') then
timer_intr <= '0';
end if;
end if;
end process;
end arch;