325 lines
11 KiB
VHDL
325 lines
11 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
entity dma_31ch is
|
|
generic(
|
|
channel_config_g : std_logic_vector(3 downto 0) := "1011";
|
|
channel_count_g : integer range 1 to 31 := 31
|
|
);
|
|
port(
|
|
-- Generic I/O
|
|
dma_clk : in std_logic;
|
|
dma_rst : in std_logic;
|
|
-- Trigger inputs (only valid if dma channel is inactive)
|
|
dma_trig : in std_logic_vector(channel_count_g - 1 downto 0);
|
|
-- Interrupt output
|
|
inta : out std_logic;
|
|
|
|
-- Config interface (Avalon slave)
|
|
dma_conf_write : in std_logic;
|
|
dma_conf_read : in std_logic;
|
|
dma_conf_cs : in std_logic;
|
|
dma_conf_waitrequest : out std_logic;
|
|
dma_conf_data_from_dma : out std_logic_vector(31 downto 0);
|
|
dma_conf_data_to_dma : in std_logic_vector(31 downto 0);
|
|
dma_conf_addr : in std_logic_vector(15 downto 0);
|
|
dma_conf_response : out std_logic_vector(1 downto 0);
|
|
-- DMA Master Interface 0
|
|
dma_mst0_write : out std_logic;
|
|
dma_mst0_read : out std_logic;
|
|
dma_mst0_cs : out std_logic;
|
|
dma_mst0_waitrequest : in std_logic;
|
|
dma_mst0_data_to_dma : in std_logic_vector(31 downto 0);
|
|
dma_mst0_data_from_dma : out std_logic_vector(31 downto 0);
|
|
dma_mst0_addr : out std_logic_vector(31 downto 0);
|
|
-- DMA Master Interface 1
|
|
dma_mst1_write : out std_logic;
|
|
dma_mst1_read : out std_logic;
|
|
dma_mst1_cs : out std_logic;
|
|
dma_mst1_waitrequest : in std_logic;
|
|
dma_mst1_data_to_dma : in std_logic_vector(31 downto 0);
|
|
dma_mst1_data_from_dma : out std_logic_vector(31 downto 0);
|
|
dma_mst1_addr : out std_logic_vector(31 downto 0)
|
|
);
|
|
end entity dma_31ch;
|
|
|
|
architecture RTL of dma_31ch is
|
|
constant ch_conf : std_logic_vector(3 downto 0) := channel_config_g;
|
|
|
|
|
|
component avalon2wb
|
|
generic(
|
|
ADDR_WIDTH_G : natural := 32;
|
|
DATA_WIDTH_G : natural := 32
|
|
);
|
|
port(
|
|
avalon_write : in std_logic;
|
|
avalon_read : in std_logic;
|
|
avalon_cs : in std_logic;
|
|
avalon_waitrequest : out std_logic;
|
|
avalon_data_in : in std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
avalon_data_out : out std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
avalon_address : in std_logic_vector(ADDR_WIDTH_G - 1 downto 0);
|
|
avalon_response : out std_logic_vector(1 downto 0);
|
|
wb_cyc : out std_logic;
|
|
wb_we : out std_logic;
|
|
wb_stb : out std_logic;
|
|
wb_ack : in std_logic;
|
|
wb_address : out std_logic_vector(ADDR_WIDTH_G - 1 downto 0);
|
|
wb_data_out : out std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
wb_data_in : in std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
wb_err_i : in std_logic;
|
|
wb_rty_i : in std_logic
|
|
);
|
|
end component avalon2wb;
|
|
|
|
component wb2avalon
|
|
generic(
|
|
ADDR_WIDTH_G : natural := 32;
|
|
DATA_WIDTH_G : natural := 32
|
|
);
|
|
port(
|
|
avalon_write : out std_logic;
|
|
avalon_read : out std_logic;
|
|
avalon_cs : out std_logic;
|
|
avalon_waitrequest : in std_logic;
|
|
avalon_data_in : in std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
avalon_data_out : out std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
avalon_address : out std_logic_vector(ADDR_WIDTH_G - 1 downto 0);
|
|
wb_cyc : in std_logic;
|
|
wb_we : in std_logic;
|
|
wb_stb : in std_logic;
|
|
wb_ack : out std_logic;
|
|
wb_address : in std_logic_vector(ADDR_WIDTH_G - 1 downto 0);
|
|
wb_data_out : out std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
wb_data_in : in std_logic_vector(DATA_WIDTH_G - 1 downto 0);
|
|
wb_err : out std_logic;
|
|
wb_rty : out std_logic
|
|
);
|
|
end component wb2avalon;
|
|
|
|
-- Wishbone Config interface
|
|
signal wb_conf_addr : std_logic_vector(31 downto 0);
|
|
signal wb_conf_data_to_dma : std_logic_vector(31 downto 0);
|
|
signal wb_conf_data_from_dma : std_logic_vector(31 downto 0);
|
|
signal wb_conf_sel : std_logic_vector(3 downto 0);
|
|
signal wb_conf_we : std_logic;
|
|
signal wb_conf_cyc : std_logic;
|
|
signal wb_conf_stb : std_logic;
|
|
signal wb_conf_ack : std_logic;
|
|
signal wb_conf_err : std_logic;
|
|
signal wb_conf_rty : std_logic;
|
|
-- Wishbone Master Interface 0
|
|
signal wb_m0_addr : std_logic_vector(31 downto 0);
|
|
signal wb_m0_data_to_dma : std_logic_vector(31 downto 0);
|
|
signal wb_m0_data_from_dma : std_logic_vector(31 downto 0);
|
|
signal wb_m0_sel : std_logic_vector(3 downto 0);
|
|
signal wb_m0_we : std_logic;
|
|
signal wb_m0_cyc : std_logic;
|
|
signal wb_m0_stb : std_logic;
|
|
signal wb_m0_ack : std_logic;
|
|
signal wb_m0_err : std_logic;
|
|
signal wb_m0_rty : std_logic;
|
|
-- Wishbone Master Interface 1
|
|
signal wb_m1_addr : std_logic_vector(31 downto 0);
|
|
signal wb_m1_data_to_dma : std_logic_vector(31 downto 0);
|
|
signal wb_m1_data_from_dma : std_logic_vector(31 downto 0);
|
|
signal wb_m1_sel : std_logic_vector(3 downto 0);
|
|
signal wb_m1_we : std_logic;
|
|
signal wb_m1_cyc : std_logic;
|
|
signal wb_m1_stb : std_logic;
|
|
signal wb_m1_ack : std_logic;
|
|
signal wb_m1_err : std_logic;
|
|
signal wb_m1_rty : std_logic;
|
|
|
|
-- DMA trigger/request signals
|
|
signal dma_req : std_logic_vector(channel_count_g - 1 downto 0);
|
|
signal dma_req_ack : std_logic_vector(channel_count_g - 1 downto 0);
|
|
|
|
-- DMA Config address Signals
|
|
signal wb_conf_addr_premask : std_logic_vector(15 downto 0);
|
|
|
|
begin
|
|
-- DMA instance
|
|
wb_dma_top_inst : entity work.wb_dma_top
|
|
generic map(
|
|
rf_addr => x"F", -- Top address width. Will be remapped by wrapper
|
|
pri_sel => "00", -- Only 1 priority
|
|
ch_count => channel_count_g,
|
|
ch0_conf => ch_conf,
|
|
ch1_conf => ch_conf,
|
|
ch2_conf => ch_conf,
|
|
ch3_conf => ch_conf,
|
|
ch4_conf => ch_conf,
|
|
ch5_conf => ch_conf,
|
|
ch6_conf => ch_conf,
|
|
ch7_conf => ch_conf,
|
|
ch8_conf => ch_conf,
|
|
ch9_conf => ch_conf,
|
|
ch10_conf => ch_conf,
|
|
ch11_conf => ch_conf,
|
|
ch12_conf => ch_conf,
|
|
ch13_conf => ch_conf,
|
|
ch14_conf => ch_conf,
|
|
ch15_conf => ch_conf,
|
|
ch16_conf => ch_conf,
|
|
ch17_conf => ch_conf,
|
|
ch18_conf => ch_conf,
|
|
ch19_conf => ch_conf,
|
|
ch20_conf => ch_conf,
|
|
ch21_conf => ch_conf,
|
|
ch22_conf => ch_conf,
|
|
ch23_conf => ch_conf,
|
|
ch24_conf => ch_conf,
|
|
ch25_conf => ch_conf,
|
|
ch26_conf => ch_conf,
|
|
ch27_conf => ch_conf,
|
|
ch28_conf => ch_conf,
|
|
ch29_conf => ch_conf,
|
|
ch30_conf => ch_conf
|
|
)
|
|
port map(
|
|
clk_i => dma_clk,
|
|
rst_i => dma_rst,
|
|
wb0s_data_i => wb_conf_data_to_dma,
|
|
wb0s_data_o => wb_conf_data_from_dma,
|
|
wb0_addr_i => wb_conf_addr,
|
|
wb0_sel_i => wb_conf_sel,
|
|
wb0_we_i => wb_conf_we,
|
|
wb0_cyc_i => wb_conf_cyc,
|
|
wb0_stb_i => wb_conf_stb,
|
|
wb0_ack_o => wb_conf_ack,
|
|
wb0_err_o => wb_conf_err,
|
|
wb0_rty_o => wb_conf_rty,
|
|
wb0m_data_i => wb_m0_data_to_dma,
|
|
wb0m_data_o => wb_m0_data_from_dma,
|
|
wb0_addr_o => wb_m0_addr,
|
|
wb0_sel_o => wb_m0_sel,
|
|
wb0_we_o => wb_m0_we,
|
|
wb0_cyc_o => wb_m0_cyc,
|
|
wb0_stb_o => wb_m0_stb,
|
|
wb0_ack_i => wb_m0_ack,
|
|
wb0_err_i => wb_m0_err,
|
|
wb0_rty_i => wb_m0_rty,
|
|
wb1s_data_i => (others => '0'),
|
|
wb1s_data_o => open,
|
|
wb1_addr_i => open,
|
|
wb1_sel_i => open,
|
|
wb1_we_i => open,
|
|
wb1_cyc_i => open,
|
|
wb1_stb_i => open,
|
|
wb1_ack_o => open,
|
|
wb1_err_o => open,
|
|
wb1_rty_o => open,
|
|
wb1m_data_i => wb_m1_data_to_dma,
|
|
wb1m_data_o => wb_m1_data_from_dma,
|
|
wb1_addr_o => wb_m1_addr,
|
|
wb1_sel_o => wb_m1_sel,
|
|
wb1_we_o => wb_m1_we,
|
|
wb1_cyc_o => wb_m1_cyc,
|
|
wb1_stb_o => wb_m1_stb,
|
|
wb1_ack_i => wb_m1_ack,
|
|
wb1_err_i => wb_m1_err,
|
|
wb1_rty_i => wb_m1_rty,
|
|
dma_req_i => dma_req,
|
|
dma_nd_i => (others => '0'),
|
|
dma_ack_o => dma_req_ack,
|
|
dma_rest_i => (others => '0'),
|
|
inta_o => inta,
|
|
intb_o => open
|
|
);
|
|
|
|
config_iface: avalon2wb
|
|
generic map(
|
|
ADDR_WIDTH_G => 16,
|
|
DATA_WIDTH_G => 32
|
|
)
|
|
port map(
|
|
avalon_write => dma_conf_write,
|
|
avalon_read => dma_conf_read,
|
|
avalon_cs => dma_conf_cs,
|
|
avalon_waitrequest => dma_conf_waitrequest,
|
|
avalon_data_in => dma_conf_data_to_dma,
|
|
avalon_data_out => dma_conf_data_from_dma,
|
|
avalon_address => dma_conf_addr,
|
|
avalon_response => dma_conf_response,
|
|
wb_cyc => wb_conf_cyc,
|
|
wb_we => wb_conf_we,
|
|
wb_stb => wb_conf_stb,
|
|
wb_ack => wb_conf_ack,
|
|
wb_address => wb_conf_addr_premask,
|
|
wb_data_out => wb_conf_data_to_dma,
|
|
wb_data_in => wb_conf_data_from_dma,
|
|
wb_err_i => wb_conf_err,
|
|
wb_rty_i => wb_conf_rty
|
|
);
|
|
|
|
master_ifac0: wb2avalon
|
|
generic map(
|
|
ADDR_WIDTH_G => 32,
|
|
DATA_WIDTH_G => 32
|
|
)
|
|
port map(
|
|
avalon_write => dma_mst0_write,
|
|
avalon_read => dma_mst0_read,
|
|
avalon_cs => dma_mst0_cs,
|
|
avalon_waitrequest => dma_mst0_waitrequest,
|
|
avalon_data_in => dma_mst0_data_to_dma,
|
|
avalon_data_out => dma_mst0_data_from_dma,
|
|
avalon_address => dma_mst0_addr,
|
|
wb_cyc => wb_m0_cyc,
|
|
wb_we => wb_m0_we,
|
|
wb_stb => wb_m0_stb,
|
|
wb_ack => wb_m0_ack,
|
|
wb_address => wb_m0_addr,
|
|
wb_data_out => wb_m0_data_to_dma,
|
|
wb_data_in => wb_m0_data_from_dma,
|
|
wb_err => wb_m0_err,
|
|
wb_rty => wb_m0_rty
|
|
);
|
|
|
|
master_iface1: wb2avalon
|
|
generic map(
|
|
ADDR_WIDTH_G => 32,
|
|
DATA_WIDTH_G => 32
|
|
)
|
|
port map(
|
|
avalon_write => dma_mst1_write,
|
|
avalon_read => dma_mst1_read,
|
|
avalon_cs => dma_mst1_cs,
|
|
avalon_waitrequest => dma_mst1_waitrequest,
|
|
avalon_data_in => dma_mst1_data_to_dma,
|
|
avalon_data_out => dma_mst1_data_from_dma,
|
|
avalon_address => dma_mst1_addr,
|
|
wb_cyc => wb_m1_cyc,
|
|
wb_we => wb_m1_we,
|
|
wb_stb => wb_m1_stb,
|
|
wb_ack => wb_m1_ack,
|
|
wb_address => wb_m1_addr,
|
|
wb_data_out => wb_m1_data_to_dma,
|
|
wb_data_in => wb_m1_data_from_dma,
|
|
wb_err => wb_m1_err,
|
|
wb_rty => wb_m1_rty
|
|
);
|
|
-- DMA config address range is at the "top" of 32-bit address space beginning at 0xF0000000
|
|
wb_conf_addr <= x"F000" & wb_conf_addr_premask;
|
|
|
|
trigger_handshake : for i in 0 to channel_count_g - 1 generate
|
|
handshake_proc : process(dma_clk, dma_rst) is
|
|
begin
|
|
if dma_rst = '1' then
|
|
dma_req <= (others => '0');
|
|
elsif rising_edge(dma_clk) then
|
|
if dma_req_ack(i) = '1' and dma_req(i) = '1' then
|
|
dma_req(i) <= '0';
|
|
elsif dma_trig(i) = '1' then
|
|
dma_req(i) <= '1';
|
|
end if;
|
|
end if;
|
|
end process handshake_proc;
|
|
|
|
end generate trigger_handshake;
|
|
|
|
end architecture RTL;
|