Для AXI Master не забудьте про "multiple outstanding transactions".
Вот код для примера, тоже для себя делали:
axi_controller_dma.vhd
CODE
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library unisim;
use unisim.vcomponents.all;
entity AXI_CONTROLLER_DMA is
generic (C_S_AXI_BASEADDR : std_logic_vector(31 downto 0) := X"FFFF0000";
C_S_AXI_HIGHADDR : std_logic_vector(31 downto 0) := X"FFFFFFFF");
port (
-- AXI Slave Interface
AXI_ACLK : in std_logic;
AXI_RESETN : in std_logic;
-- AXI Slave Write Address Channel
S_AXI_AWADDR : in std_logic_vector(31 downto 0);
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
-- AXI Slave Write Data Channel
S_AXI_WDATA : in std_logic_vector(31 downto 0);
S_AXI_WSTRB : in std_logic_vector(3 downto 0);
S_AXI_WVALID : in std_logic;
S_AXI_WREADY : out std_logic;
--AXI4 Write Response Channel
S_AXI_BRESP : out std_logic_vector(1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
-- AXI Slave Read Address Channel
S_AXI_ARADDR : in std_logic_vector(31 downto 0);
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
-- AXI Slave Read Data Channel
S_AXI_RDATA : out std_logic_vector(31 downto 0);
S_AXI_RRESP : out std_logic_vector(1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic;
-- AXI4 Master Write Channel
-- Write Address Channel
M_AXI_AWREADY : in std_logic;
M_AXI_AWVALID : out std_logic;
M_AXI_AWADDR : out std_logic_vector(31 downto 0);
M_AXI_AWLEN : out std_logic_vector(7 downto 0);
M_AXI_AWSIZE : out std_logic_vector(2 downto 0);
M_AXI_AWBURST : out std_logic_vector(1 downto 0);
M_AXI_AWPROT : out std_logic_vector(2 downto 0);
M_AXI_AWCACHE : out std_logic_vector(3 downto 0);
-- Write Data Channel
M_AXI_WREADY : in std_logic ;
M_AXI_WVALID : out std_logic;
M_AXI_WDATA : out std_logic_vector(63 downto 0);
M_AXI_WSTRB : out std_logic_vector(7 downto 0);
M_AXI_WLAST : out std_logic;
-- Write Response Channel
M_AXI_BREADY : out std_logic;
M_AXI_BVALID : in std_logic;
M_AXI_BRESP : in std_logic_vector(1 downto 0)
);
end AXI_CONTROLLER_DMA;
architecture RTL of AXI_CONTROLLER_DMA is
component m_axi_users_bridge
port (
-- axi slave interface
axi_aclk : in std_logic;
axi_resetn : in std_logic;
------------------------------
-- axi4 master write channel
------------------------------
-- write address channel
m_axi_awready : in std_logic;
m_axi_awvalid : out std_logic;
m_axi_awaddr : out std_logic_vector(31 downto 0);
m_axi_awlen : out std_logic_vector(7 downto 0);
m_axi_awsize : out std_logic_vector(2 downto 0);
m_axi_awburst : out std_logic_vector(1 downto 0);
m_axi_awprot : out std_logic_vector(2 downto 0);
m_axi_awcache : out std_logic_vector(3 downto 0);
-- write data channel
m_axi_wready : in std_logic ;
m_axi_wvalid : out std_logic;
m_axi_wdata : out std_logic_vector(63 downto 0);
m_axi_wstrb : out std_logic_vector(7 downto 0);
m_axi_wlast : out std_logic;
-- write response channel
m_axi_bready : out std_logic;
m_axi_bvalid : in std_logic;
m_axi_bresp : in std_logic_vector(1 downto 0);
------------------------------
-- write user channel
------------------------------
user_wr_req : in std_logic;
user_wr_addr : in std_logic_vector(31 downto 0);
user_wr_lenght : in std_logic_vector(15 downto 0);
user_wr_ack : out std_logic;
user_wr_tvalid : in std_logic;
user_wr_tdata : in std_logic_vector(63 downto 0);
user_wr_tlast : in std_logic;
user_wr_tready : out std_logic);
end component;
component s_axi_user_bridge
port(
axi_aclk : in std_logic;
axi_resetn : in std_logic;
-- AXI Slave Write Address Channel
s_axi_awaddr : in std_logic_vector(31 downto 0);
s_axi_awvalid : in std_logic;
s_axi_awready : out std_logic;
s_axi_awprot : in std_logic_vector(2 downto 0);
-- AXI Slave Write Data Channel
s_axi_wdata : in std_logic_vector(31 downto 0);
s_axi_wstrb : in std_logic_vector(3 downto 0);
s_axi_wvalid : in std_logic;
s_axi_wready : out std_logic;
-- AXI4 Write Response Channel
s_axi_bresp : out std_logic_vector(1 downto 0);
s_axi_bvalid : out std_logic;
s_axi_bready : in std_logic;
-- AXI Slave Read Address Channel
s_axi_araddr : in std_logic_vector(31 downto 0);
s_axi_arvalid : in std_logic;
s_axi_arready : out std_logic;
s_axi_arprot : in std_logic_vector(2 downto 0);
-- AXI Slave Read Data Channel
s_axi_rdata : out std_logic_vector(31 downto 0);
s_axi_rresp : out std_logic_vector(1 downto 0);
s_axi_rvalid : out std_logic;
s_axi_rready : in std_logic ;
-- User Read/Write Data Channel
user_reset : out std_logic;
user_addr : out std_logic_vector(31 downto 0);
user_wdata : out std_logic_vector(31 downto 0);
user_rdata : in std_logic_vector(31 downto 0);
user_be : out std_logic_vector(3 downto 0);
user_wreq : out std_logic;
user_wack : in std_logic;
user_rreq : out std_logic;
user_rack : in std_logic);
end component;
function n_dec_bit(baddr,haddr : std_logic_vector(31 downto 0)) return integer is
variable baddr_xor_haddr : std_logic_vector(31 downto 0);
begin
baddr_xor_haddr := baddr xor haddr;
for i in 31 downto 0 loop
if baddr_xor_haddr(i) = '1' then
return(i+1);
end if;
end loop;
return(32);
end function n_dec_bit;
constant c_s_axi_n_dec_bit : integer := n_dec_bit(C_S_AXI_BASEADDR,C_S_AXI_HIGHADDR)-1;
constant ADR_REG_BASEADDR : std_logic_vector(31 downto 0) := X"00000000";
constant LENGHT_REG_BASEADDR : std_logic_vector(31 downto 0) := X"00000004";
constant CNT_REG_BASEADDR : std_logic_vector(31 downto 0) := X"00000008";
--constant TIME_REG_BASEADDR : std_logic_vector(31 downto 0) := X"0000000c";
constant adr_reg_n_dec_bit : integer := n_dec_bit(ADR_REG_BASEADDR, X"00000003");
constant lenght_reg_n_dec_bit : integer := n_dec_bit(LENGHT_REG_BASEADDR, X"00000007");
constant cnt_reg_n_dec_bit : integer := n_dec_bit(CNT_REG_BASEADDR, X"0000000B");
--constant time_reg_n_dec_bit : integer := n_dec_bit(time_reg_BASEADDR, X"0000000f");
-- User Read/Write signals
signal user_reset : std_logic;
signal user_addr : std_logic_vector(31 downto 0);
signal user_wdata : std_logic_vector(31 downto 0);
signal user_rdata : std_logic_vector(31 downto 0);
signal user_be : std_logic_vector(3 downto 0);
signal user_wreq : std_logic;
signal user_wack : std_logic;
signal user_rreq : std_logic;
signal user_rack : std_logic;
signal read_addr : std_logic_vector(2 downto 0);
signal adr_reg : std_logic_vector(31 downto 0);
signal lenght_reg : std_logic_vector(31 downto 0);
signal cnt_reg : std_logic_vector(31 downto 0) := (others=>'0');
signal adr_reg_ce : std_logic;
signal lenght_reg_ce : std_logic;
signal cnt_reg_ce : std_logic;
--signal time_reg_ce : std_logic;
signal dac_count : std_logic_vector(13 downto 0);
signal m_user_wr_req : std_logic;
signal m_user_wr_addr : std_logic_vector(31 downto 0) := (others=>'0');
signal m_user_wr_lenght : std_logic_vector(16 downto 0) := (others=>'0');
signal m_user_wr_ack : std_logic;
signal m_user_wr_tvalid : std_logic := '0';
signal m_user_wr_tdata : std_logic_vector(63 downto 0) := (others=>'0');
signal m_user_wr_tdata_i : std_logic_vector(31 downto 0) := (others=>'0');
signal m_user_wr_tdata_j : std_logic_vector(31 downto 0) := (others=>'0');
signal m_user_wr_tlast : std_logic := '0';
signal m_user_wr_tready : std_logic := '0';
signal time_reg : std_logic_vector(31 downto 0) := (others=>'0');
signal count_time_reg_en , count_lenght_en : std_logic := '0';
type state_type is (ST_IDLE, ST_DATA);
signal state ,next_state : state_type;
begin
-----------------------------------------------------------
-----------------------------------------------------------
s_axi_user_bridge_inst : s_axi_user_bridge
port map(
axi_aclk => AXI_ACLK,
axi_resetn => AXI_RESETN,
s_axi_awaddr => s_axi_awaddr,
s_axi_awvalid => s_axi_awvalid,
s_axi_awready => s_axi_awready,
s_axi_awprot => s_axi_awprot,
s_axi_wdata => s_axi_wdata,
s_axi_wstrb => s_axi_wstrb,
s_axi_wvalid => s_axi_wvalid,
s_axi_wready => s_axi_wready,
s_axi_bresp => s_axi_bresp,
s_axi_bvalid => s_axi_bvalid,
s_axi_bready => s_axi_bready,
s_axi_araddr => s_axi_araddr,
s_axi_arvalid => s_axi_arvalid,
s_axi_arready => s_axi_arready,
s_axi_arprot => s_axi_arprot,
s_axi_rdata => s_axi_rdata,
s_axi_rresp => s_axi_rresp,
s_axi_rvalid => s_axi_rvalid,
s_axi_rready => s_axi_rready,
user_reset => user_reset,
user_addr => user_addr,
user_wdata => user_wdata,
user_rdata => user_rdata,
user_be => user_be,
user_wreq => user_wreq,
user_wack => user_wack,
user_rreq => user_rreq,
user_rack => user_rack);
-----------------------------------------------------------
adr_reg_ce <= '1' when (user_addr(c_s_axi_n_dec_bit downto adr_reg_n_dec_bit) = ADR_REG_BASEADDR(c_s_axi_n_dec_bit downto adr_reg_n_dec_bit)) else '0';
lenght_reg_ce <= '1' when (user_addr(c_s_axi_n_dec_bit downto lenght_reg_n_dec_bit) = LENGHT_REG_BASEADDR(c_s_axi_n_dec_bit downto lenght_reg_n_dec_bit)) else '0';
cnt_reg_ce <= '1' when (user_addr(c_s_axi_n_dec_bit downto cnt_reg_n_dec_bit) = CNT_REG_BASEADDR(c_s_axi_n_dec_bit downto cnt_reg_n_dec_bit)) else '0';
--time_reg_ce <= '1' when (user_addr(c_s_axi_n_dec_bit downto time_reg_n_dec_bit) = TIME_REG_BASEADDR(c_s_axi_n_dec_bit downto time_reg_n_dec_bit)) else '0';
-- User Write Data Channel
user_wack <= '1' when (user_wreq = '1' and (lenght_reg_ce = '1' or adr_reg_ce = '1' or cnt_reg_ce = '1')) else '0';
user_rack <= user_rreq;
process ( AXI_ACLK , user_reset )
begin
if ( AXI_ACLK = '1' and AXI_ACLK 'event) then
if (user_reset ='1') then
adr_reg <= (others => '0');
lenght_reg <= (others => '0');
elsif (user_wreq = '1') then
if ( adr_reg_ce = '1') then
adr_reg <= user_wdata;
end if;
if ( lenght_reg_ce = '1') then
lenght_reg <= user_wdata;
end if;
-- if ( cnt_reg_ce = '1') then
-- cnt_reg <= user_wdata;
-- end if;
end if;
end if;
end process;
-----------------------------------------------------------
-- AXI Slave_User Read Data Channel
read_addr <= user_addr(4 downto 2);
process (read_addr, cnt_reg, adr_reg, lenght_reg, cnt_reg, time_reg)
begin
case (read_addr) is
when "000" =>
user_rdata <= adr_reg;
when "001" =>
user_rdata <= lenght_reg;
when "010" =>
user_rdata <= cnt_reg;
when "011" =>
user_rdata <= time_reg;
when others =>
user_rdata <= x"ffffffff";
end case;
end process;
-----------------------------------------------------------
-----------------------------------------------------------
m_axi_users_bridge_inst: m_axi_users_bridge
port map(
axi_aclk => axi_aclk,
axi_resetn => axi_resetn,
m_axi_awready => m_axi_awready,
m_axi_awvalid => m_axi_awvalid,
m_axi_awaddr => m_axi_awaddr,
m_axi_awlen => m_axi_awlen,
m_axi_awsize => m_axi_awsize,
m_axi_awburst => m_axi_awburst,
m_axi_awprot => m_axi_awprot,
m_axi_awcache => m_axi_awcache,
m_axi_wready => m_axi_wready,
m_axi_wvalid => m_axi_wvalid,
m_axi_wdata => m_axi_wdata,
m_axi_wstrb => m_axi_wstrb,
m_axi_wlast => m_axi_wlast,
m_axi_bready => m_axi_bready,
m_axi_bvalid => m_axi_bvalid,
m_axi_bresp => m_axi_bresp,
user_wr_req => m_user_wr_req,
user_wr_addr => m_user_wr_addr,
user_wr_lenght => lenght_reg(15 downto 0),
user_wr_ack => m_user_wr_ack,
user_wr_tvalid => m_user_wr_tvalid,
user_wr_tdata => m_user_wr_tdata,
user_wr_tlast => m_user_wr_tlast,
user_wr_tready => m_user_wr_tready);
-----------------------------------------------------------
m_user_wr_addr <= adr_reg;
-----------------------------------------------------------
process (AXI_ACLK, user_reset)
begin
if (AXI_ACLK'event and AXI_ACLK = '1') then
if (user_reset = '1') then
state <= ST_IDLE;
else
state <= next_state;
end if;
end if;
end process;
process (state, cnt_reg_ce, user_wreq, user_wdata, m_user_wr_ack, m_user_wr_lenght,m_user_wr_tready)
begin
m_user_wr_req <= '0';
m_user_wr_tvalid <= '0';
m_user_wr_tlast <= '0';
count_time_reg_en <= '0';
cnt_reg(0) <= '0';
next_state <= state;
case state is
when ST_IDLE =>
if (cnt_reg_ce = '1' and user_wreq = '1' and user_wdata(0) = '1') then
m_user_wr_req <= '1';
cnt_reg(0) <= '1';
end if;
if( m_user_wr_ack = '1') then
cnt_reg(0) <= '1';
next_state <= ST_DATA;
end if;
when ST_DATA =>
cnt_reg(0) <= '1';
m_user_wr_tvalid <= '1';
m_user_wr_tlast <= m_user_wr_lenght(16);
if(m_user_wr_lenght(16) = '1' and m_user_wr_tready = '1') then
next_state <= ST_IDLE;
end if;
end case;
end process;
-----------------------------------------------------------
process (AXI_ACLK)
begin
if (AXI_ACLK'event and AXI_ACLK = '1') then
if (m_user_wr_ack = '1') then
time_reg <= (others=>'0');
elsif (cnt_reg(0) = '1') then--
time_reg <= time_reg + 1;
end if;
end if;
end process;
-----------------------------------------------------------
process (AXI_ACLK)
begin
if (AXI_ACLK'event and AXI_ACLK = '1') then
if (m_user_wr_ack = '1') then
m_user_wr_tdata_i <= (others=>'0');
m_user_wr_tdata_j <= x"00000001";--
elsif (m_user_wr_tready = '1') then
m_user_wr_tdata_i <= m_user_wr_tdata_i + 2;
m_user_wr_tdata_j <= m_user_wr_tdata_j + 2;
end if;
end if;
end process;
m_user_wr_tdata <= x"00000000" & m_user_wr_tdata_i;--m_user_wr_tdata_j
-----------------------------------------------------------
process (AXI_ACLK)
begin
if (AXI_ACLK'event and AXI_ACLK = '1') then
if (m_user_wr_ack = '1') then
m_user_wr_lenght <= ('0'&lenght_reg(15 downto 0)) - 1;
elsif (m_user_wr_tready = '1') then
m_user_wr_lenght <= m_user_wr_lenght - 1;
end if;
end if;
end process;
-----------------------------------------------------------
-----------------------------------------------------------
end RTL;
m_axi_user_bridge.vhd
CODE
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
library unisim;
use unisim.vcomponents.all;
entity M_AXI_USERS_BRIDGE is
port (
-- AXI Interface
AXI_ACLK : in std_logic;
AXI_RESETN : in std_logic;
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- AXI4 Master Write Channel
-----------------------------------------------------------------------------
-- Write Address Channel
M_AXI_AWREADY : in std_logic;
M_AXI_AWVALID : out std_logic;
M_AXI_AWADDR : out std_logic_vector(31 downto 0);
M_AXI_AWLEN : out std_logic_vector(7 downto 0);
M_AXI_AWSIZE : out std_logic_vector(2 downto 0);
M_AXI_AWBURST : out std_logic_vector(1 downto 0);
M_AXI_AWPROT : out std_logic_vector(2 downto 0);
M_AXI_AWCACHE : out std_logic_vector(3 downto 0);
-- Write Data Channel
M_AXI_WREADY : in std_logic ;
M_AXI_WVALID : out std_logic;
M_AXI_WDATA : out std_logic_vector(63 downto 0);
M_AXI_WSTRB : out std_logic_vector(7 downto 0);
M_AXI_WLAST : out std_logic;
-- Write Response Channel
M_AXI_BREADY : out std_logic;
M_AXI_BVALID : in std_logic;
M_AXI_BRESP : in std_logic_vector(1 downto 0);
-----------------------------------------------------------------------------
-- Write User Channel
-----------------------------------------------------------------------------
USER_WR_REQ : in std_logic;
USER_WR_ADDR : in std_logic_vector(31 downto 0);
USER_WR_LENGHT : in std_logic_vector(15 downto 0);
USER_WR_ACK : out std_logic;
USER_WR_TVALID : in std_logic;
USER_WR_TDATA : in std_logic_vector(63 downto 0);
USER_WR_TLAST : in std_logic;
USER_WR_TREADY : out std_logic
);
end M_AXI_USERS_BRIDGE;
architecture RTL of M_AXI_USERS_BRIDGE is
type state_type is (ST_IDLE, ST_ADDR);
signal state, next_state : state_type;
signal count_awlen : std_logic_vector(16 downto 0):= (others => '0');
signal count_awaddr : std_logic_vector(31 downto 0):= (others => '0');
signal count_addr_load : std_logic;
signal count_addr_en : std_logic;
signal count_data : std_logic_vector(4 downto 0):= (others => '0');
signal count_data_init : std_logic;
signal count_data_en : std_logic;
signal count_addr_que : std_logic_vector(4 downto 0):= (others => '0');
-----------------------------------------------------------------------
begin
M_AXI_AWSIZE <= "011";
M_AXI_AWBURST <= "01";
M_AXI_AWPROT <= (others => '0');
M_AXI_AWCACHE <= (others => '0');
M_AXI_WSTRB <= x"ff";
M_AXI_BREADY <= '1';
M_AXI_AWADDR <= count_awaddr;
M_AXI_AWLEN <= x"0f" when( count_awlen(16) = '0') else "0000" & count_awlen(3 downto 0);
M_AXI_WVALID <= USER_WR_TVALID;
M_AXI_WDATA <= USER_WR_TDATA;
USER_WR_TREADY <= M_AXI_WREADY;
-----------------------------------------------------------
-----------------------------------------------------------
process (AXI_ACLK, AXI_RESETN)
begin
if (AXI_ACLK'event and AXI_ACLK = '1') then
if (AXI_RESETN = '0') then
state <= ST_IDLE;
else
state <= next_state;
end if;
end if;
end process;
process (state, USER_WR_REQ, count_awlen, M_AXI_AWREADY)
begin
M_AXI_AWVALID <= '0';
USER_WR_ACK <= '0';
count_addr_load <= '0';
count_addr_en <= '0';
next_state <= state;
case state is
when ST_IDLE =>
if (USER_WR_REQ = '1') then
USER_WR_ACK <= '1';
count_addr_load <= '1';
next_state <= ST_ADDR;
end if;
when ST_ADDR =>
M_AXI_AWVALID <= '1';
count_addr_en <= M_AXI_AWREADY;
if (count_awlen(16) = '1' and M_AXI_AWREADY = '1') then
next_state <= ST_IDLE;
end if;
end case;
end process;
-----------------------------------------------------------
process (AXI_ACLK)
begin
if (AXI_ACLK'event and AXI_ACLK = '1') then
if (count_addr_load = '1') then
count_awaddr(31 downto 3) <= USER_WR_ADDR(31 downto 3);
count_awlen <= ('0'&USER_WR_LENGHT) - 16;
elsif (count_addr_en = '1') then
count_awaddr(31 downto 3) <= count_awaddr(31 downto 3) + 16;
count_awlen <= count_awlen - 16;
end if;
end if;
end process;
-----------------------------------------------------------
count_data_en <= '1' when (( USER_WR_TVALID = '1' and M_AXI_WREADY = '1') or AXI_RESETN = '0') else '0';
count_data_init <= '1' when ((count_data(4) = '1' or USER_WR_TLAST = '1') or AXI_RESETN = '0') else '0';
M_AXI_WLAST <= count_data_init;
-----------------------------------------------------------
process (AXI_ACLK)
begin
if (AXI_ACLK'event and AXI_ACLK = '1') then
if (count_data_en = '1') then
if (count_data_init = '1') then
count_data <= "00000" + 1;
else
count_data <= count_data + 1;
end if;
end if;
end if;
end process;
-----------------------------------------------------------
end RTL;