----------------------------------------------------------------------- -- $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;