mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-02-02 06:40:51 +00:00
226 lines
7.1 KiB
VHDL
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;
|