Files
vhdl/lib/JBUS/src/dmac.vhd
T
jens 70e48af3ab - commit local changes after CVS2SVN
git-svn-id: http://moon:8086/svn/vhdl/trunk@1036 cc03376c-175c-47c8-b038-4cd826a8556b
2014-07-20 13:30:14 +00:00

231 lines
5.3 KiB
VHDL

-----------------------------------------------------------------------
-- $Header: D:\usr\cvsroot/VHDL/lib/JBUS/src/dmac.vhd,v 1.2 2013/05/28 11:23:15 jens Exp $
-----------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.utils_pkg.all;
use work.busmaster_types.all;
------------------------------------------------------------------
entity dmac is
Generic
(
DATA_WIDTH : natural := 32;
XFER_CHUNK_SIZE : natural := 512
);
Port
(
clk : in std_logic;
rst : in std_logic;
master_req : out std_logic;
master_gnt : in std_logic;
dma_start : out std_logic;
dma_active : out std_logic;
dma_end : out std_logic;
req_rdy : out std_logic;
req_en : in std_logic;
req_rw : in std_logic;
req_addr_start : in unsigned(31 downto 0);
req_num_xfers : in unsigned(31 downto 0);
req_addr_auto_inc : in std_logic;
req_complete : out std_logic;
req_complete_ack : in std_logic;
-- busmaster control
bus_cyc_complete : in std_logic;
bus_cmd_rdy : in std_logic;
bus_cmd_we : out std_logic;
bus_cmd_cycle_en : out std_logic;
-- busmaster command
bus_cmd_out : out bm_cmd_t
);
end dmac;
architecture Behavioral of dmac is
signal start_en : std_logic;
signal finish_en : std_logic;
signal complete : std_logic;
signal addr_inc_en : std_logic;
signal addr : unsigned(31 downto 0);
signal rw : std_logic;
signal req_count_en : std_logic;
signal req_count : unsigned(31 downto 0);
signal req_count_next : unsigned(32 downto 0);
signal req_count_rdy : std_logic;
signal chunk_count_rst : std_logic;
signal chunk_count_en : std_logic;
signal chunk_count : unsigned(31 downto 0);
signal chunk_count_next : unsigned(32 downto 0);
signal chunk_count_rdy : std_logic;
type state_t is (INIT, READY, START, SETUP, XFER, FINISH, DONE);
signal s, sn : state_t;
begin
bus_cmd_out.addr <= addr;
bus_cmd_out.sel <= (others => '1');
bus_cmd_out.rw <= rw;
req_complete <= complete;
state_next:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
s <= INIT;
else
s <= sn;
end if;
end if;
end process;
state:
process(s, req_en, master_gnt, req_count_rdy, chunk_count_rdy, bus_cyc_complete, bus_cmd_rdy)
begin
bus_cmd_cycle_en <= '0';
bus_cmd_we <= '0';
start_en <= '0';
finish_en <= '0';
req_count_en <= '0';
req_rdy <= '0';
chunk_count_rst <= '0';
chunk_count_en <= '0';
master_req <= '0';
dma_start <= '0';
dma_active <= '0';
dma_end <= '0';
sn <= s;
case s is
when INIT =>
sn <= READY;
when READY =>
req_rdy <= '1';
if req_en = '1' then
start_en <= '1';
sn <= SETUP;
end if;
when SETUP =>
dma_start <= '1';
sn <= START;
when START =>
master_req <= '1';
chunk_count_rst <= '1';
if req_count_rdy = '1' then
sn <= READY;
elsif master_gnt = '1' and bus_cyc_complete = '1' then
sn <= XFER;
end if;
when XFER =>
dma_active <= '1';
master_req <= '1';
bus_cmd_we <= '1';
bus_cmd_cycle_en <= '1';
req_count_en <= bus_cmd_rdy;
chunk_count_en <= bus_cmd_rdy;
if req_count_rdy = '1' then
sn <= FINISH;
elsif chunk_count_rdy = '1' then
sn <= START;
end if;
when FINISH =>
master_req <= '1';
dma_end <= '1';
sn <= DONE;
when DONE =>
master_req <= '1';
if bus_cyc_complete = '1' then
sn <= READY;
finish_en <= '1';
end if;
when others =>
sn <= READY;
end case;
end process;
addr_gen:
process(clk)
begin
if rising_edge(clk) then
if start_en = '1' then
rw <= req_rw;
addr <= req_addr_start;
addr_inc_en <= req_addr_auto_inc;
elsif req_count_en = '1' and addr_inc_en = '1' then
addr <= addr + DATA_WIDTH/8;
end if;
end if;
end process;
req_count_next <= ('0' & req_num_xfers) - 1 when start_en = '1' else ('0' & req_count) - 1;
req_count_rdy <= req_count_next(32);
req_counter:
process(clk)
begin
if rising_edge(clk) then
if start_en = '1' then
req_count <= req_count_next(31 downto 0);
elsif req_count_en = '1' then
if req_count_rdy = '0' then
req_count <= req_count_next(31 downto 0);
end if;
end if;
end if;
end process;
chunk_count_next <= to_unsigned(XFER_CHUNK_SIZE, 33) - 1 when chunk_count_rst = '1' else ('0' & chunk_count) - 1;
chunk_count_rdy <= chunk_count_next(32);
chunk_counter:
process(clk)
begin
if rising_edge(clk) then
if chunk_count_rst = '1' then
chunk_count <= chunk_count_next(31 downto 0);
elsif chunk_count_en = '1' then
if chunk_count_rdy = '0' then
chunk_count <= chunk_count_next(31 downto 0);
end if;
end if;
end if;
end process;
complete_register:
process(clk)
begin
if rising_edge(clk) then
if start_en = '1' or rst = '1' then
complete <= '0';
elsif complete = '0' then
if finish_en = '1' then
complete <= '1';
elsif req_complete_ack = '1' then
complete <= '0';
end if;
end if;
end if;
end process;
end Behavioral;