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