- Specification of AXI Stream interface
- Creating a custom AXI-Streaming IP in Vivado
- Example video to create a custom AXI Stream IP with vivado
On Vivado you can generate a module with axi stream port with Tools > Create and package an IP, or creating a VHDL file and add the axi interphase by putting the correct labels to the input and the outputs. It is necessary to have the inputs / outputs as signalname_tvalid, signalname_tdata, signalname_tready for the Vivado to interpret it as a Master/Slave AXI-Stream input or output.
Generic properties of a AXI module:
-- Parameters of Axi Slave Bus Interface S00_AXIS
C_S_AXIS_TDATA_WIDTH : integer := 32;
-- Parameters of Axi Master Bus Interface M00_AXIS
C_M_AXIS_TDATA_WIDTH : integer := 32;
Output Master Axis port:
aclk : in std_logic;
m_axis_tvalid : out std_logic;
m_axis_tdata : out std_logic_vector(C_S_AXIS_TDATA_WIDTH-1 downto 0);
m_axis_tready : in std_logic;
-- OPTIONAL
m_axis_aresetn : in std_logic; -- Negative input
m_axis_tlast : out std_logic;
Slave Axis port:
aclk : in std_logic;
s_axis_tready : out std_logic;
s_axis_tdata : in std_logic_vector(C_M_AXIS_TDATA_WIDTH-1 downto 0);
s_axis_tvalid : in std_logic;
-- OPTIONAL
s_axis_aresetn : in std_logic; -- Negative input
s_axis_tlast : in std_logic;
AXIS_CONFIG
This example send a signal to a axis interface
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity axis_config is
generic (
-- Parameters of Axi Master Bus Interface M00_AXIS
C_M_AXIS_TDATA_WIDTH : integer := 32;
C_TDATA_VALUE : std_logic_vector(32-1 downto 0) := X"00000004" --! the Control Word to send
);
Port (
m_axis_aclk : in std_logic;
m_axis_aresetn : in std_logic;
m_axis_tvalid : out std_logic;
m_axis_tdata : out std_logic_vector(C_M_AXIS_TDATA_WIDTH-1 downto 0);
m_axis_tready : in std_logic
);
end axis_config;
architecture Behavioral of axis_config is
signal done : std_logic := '0'; --! 1 if config is configured, 0 otherwise
signal m_axis_tvalid_reg : std_logic := '0';
begin
m_axis_tdata <= C_TDATA_VALUE(C_M_AXIS_TDATA_WIDTH-1 downto 0);
m_axis_tvalid <= m_axis_tvalid_reg;
process(m_axis_aclk) begin
if rising_edge(m_axis_aclk) then
if m_axis_aresetn /= '1' then
done <= '0';
m_axis_tvalid_reg <= '0';
elsif (done = '1') or ((m_axis_tready = '1') and (m_axis_tvalid_reg = '1')) then
-- already done or just done right now
done <= '1';
m_axis_tvalid_reg <= '0';
else
m_axis_tvalid_reg <= '1';
done <= '0';
end if;
end if;
end process;
end Behavioral;
and the testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity axis_config_tb is
end axis_config_tb;
architecture Behavioral of axis_config_tb is
component axis_config port(
m_axis_aclk : in std_logic;
m_axis_aresetn : in std_logic;
m_axis_tvalid : out std_logic;
m_axis_tdata : out std_logic_vector;
m_axis_tready : in std_logic
);
end component;
constant C_M_AXIS_TDATA_WIDTH : integer := 32;
-- input signals
signal m_axis_aclk, m_axis_aresetn : std_logic := '1';
signal m_axis_tready : std_logic := '0';
-- output signals
signal m_axis_tvalid : std_logic := '0';
signal m_axis_tdata : std_logic_vector (C_M_AXIS_TDATA_WIDTH-1 downto 0);
--Time interval between two test vectors
constant clk_period : time := 10 ns; -- Freq of 100 MHz
begin
DUT: axis_config port map(
m_axis_aclk => m_axis_aclk,
m_axis_aresetn => m_axis_aresetn,
m_axis_tvalid => m_axis_tvalid,
m_axis_tdata => m_axis_tdata,
m_axis_tready => m_axis_tready
);
m_axis_aclk <= NOT m_axis_aclk AFTER clk_period/2;
process
begin
wait for clk_period;
m_axis_aresetn <= '1';
m_axis_tready <= '1';
wait for clk_period;
wait for clk_period;
wait for clk_period;
wait for clk_period;
end process;
end Behavioral;