Files
vhdl/lib/JBUS/src/dma.vhd
T
jens 285ebe2795 Initial revision
Committed on the Free edition of March Hare Software CVSNT Server.
Upgrade to CVS Suite for more features and support:
http://march-hare.com/cvsnt/


git-svn-id: http://moon:8086/svn/vhdl/trunk@971 cc03376c-175c-47c8-b038-4cd826a8556b
2013-05-27 11:16:41 +00:00

233 lines
5.2 KiB
VHDL

-----------------------------------------------------------------------
-- $Header: /tmp/cvsroot/VHDL/lib/JBUS/src/dma.vhd,v 1.1 2013-05-27 11:15:58 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 dma 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;
req_rdy : out std_logic;
req_rw : in std_logic;
req_en : in std_logic;
req_addr : in unsigned(31 downto 0);
req_addr_inc : in unsigned(31 downto 0);
req_num_xfers : in unsigned(31 downto 0);
req_complete : out std_logic;
req_complete_ack : in std_logic;
-- busmaster control
bus_source_en : out std_logic;
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 dma;
architecture Behavioral of dma is
signal start_en : std_logic;
signal finish_en : std_logic;
signal complete : std_logic;
signal rw : std_logic;
signal addr : unsigned(31 downto 0);
signal addr_incr : unsigned(31 downto 0);
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, SETUP, XFER_WRITE, XFER_READ, FINISH);
signal s, sn : state_t;
begin
bus_cmd_out.addr <= addr;
bus_cmd_out.sel <= "1111";
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, rw, 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';
bus_source_en <= '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 =>
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
if rw = '1' then
sn <= XFER_WRITE;
else
sn <= XFER_READ;
end if;
end if;
when XFER_WRITE =>
master_req <= '1';
bus_cmd_we <= '1';
bus_cmd_cycle_en <= '1';
req_count_en <= bus_cmd_rdy;
chunk_count_en <= bus_cmd_rdy;
bus_source_en <= '1';
if req_count_rdy = '1' then
sn <= FINISH;
elsif chunk_count_rdy = '1' then
sn <= SETUP;
end if;
when XFER_READ =>
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 <= SETUP;
end if;
when FINISH =>
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
addr <= req_addr;
addr_incr <= req_addr_inc;
rw <= req_rw;
elsif req_count_en = '1' then
addr <= addr + addr_incr;
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;