-- Sample of the AXI Stream I2S receiver library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Currently outputs data on the 3rd clock cycle after I2S_DONE is asserted. -- Could be optimized. -- Also note that there is no buffer on the input samples -- If a sample is read and the slave is not ready to receive it (TREADY is low) by the time the next sample is read (highly unlikely) -- The first sample WILL BE LOST entity i2s_axis_v1_0_I2S_L_RECV_AXIS is generic ( -- Users to add parameters here I2S_DATA_WIDTH : integer := 24; -- User parameters ends -- Do not modify the parameters beyond this line -- Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH. C_M_AXIS_TDATA_WIDTH : integer := 32 -- Start count is the numeber of clock cycles the master will wait before initiating/issuing any transaction. -- C_M_START_COUNT : integer := 32 ); port ( -- Users to add ports here I2S_L_RECV : in std_logic_vector(I2S_DATA_WIDTH-1 downto 0); I2S_DONE : in std_logic; I2S_LR_DONE : in std_logic; -- User ports ends -- Do not modify the ports beyond this line -- Global ports M_AXIS_ACLK : in std_logic; -- M_AXIS_ARESETN : in std_logic; -- Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted. M_AXIS_TVALID : out std_logic; -- TDATA is the primary payload that is used to provide the data that is passing across the interface from the master. M_AXIS_TDATA : out std_logic_vector(C_M_AXIS_TDATA_WIDTH-1 downto 0); -- TREADY indicates that the slave can accept a transfer in the current cycle. M_AXIS_TREADY : in std_logic ); end i2s_axis_v1_0_I2S_L_RECV_AXIS; architecture implementation of i2s_axis_v1_0_I2S_L_RECV_AXIS is -- Define the states of state machine -- The control state machine oversees the writing of input streaming data to the FIFO, -- and outputs the streaming data from the FIFO type state is ( IDLE, -- This is the initial/idle state INIT_COUNTER, -- This state initializes the counter, ones -- the counter reaches C_M_START_COUNT count, -- the state machine changes state to INIT_WRITE SEND_STREAM); -- In this state the -- stream data is output through M_AXIS_TDATA -- State variable signal mst_exec_state : state; -- AXI Stream internal signals signal axis_tvalid : std_logic; --streaming data valid delayed by one clock cycle signal axis_tvalid_delay : std_logic; --Last of the streaming data signal axis_tlast : std_logic; --Last of the streaming data delayed by one clock cycle signal axis_tlast_delay : std_logic; --FIFO implementation signals signal stream_data_out : std_logic_vector(C_M_AXIS_TDATA_WIDTH-1 downto 0); signal tx_en : std_logic; --The master has issued all the streaming data stored in FIFO signal tx_done : std_logic; signal data_ready : std_logic; signal prev_i2s_done : std_logic; signal L_reg : std_logic_vector(C_M_AXIS_TDATA_WIDTH-1 downto 0); begin -- I/O Connections assignments -- AND TLAST and TVALID signals together so they only last for 1 clock cycle M_AXIS_TVALID <= axis_tvalid and axis_tvalid_delay; M_AXIS_TDATA <= stream_data_out; -- Control state machine implementation process(M_AXIS_ACLK) begin if (rising_edge (M_AXIS_ACLK)) then if(M_AXIS_ARESETN = '0') then -- Synchronous reset (active low) mst_exec_state <= IDLE; else case (mst_exec_state) is when IDLE => -- The slave starts accepting tdata when -- there tvalid is asserted to mark the -- presence of valid streaming data if data_ready = '1' then mst_exec_state <= SEND_STREAM; else mst_exec_state <= IDLE; end if; when SEND_STREAM => -- The example design streaming master functionality starts -- when the master drives output tdata from the FIFO and the slave -- has finished storing the S_AXIS_TDATA if (tx_done = '1') then mst_exec_state <= IDLE; else mst_exec_state <= SEND_STREAM; end if; when others => mst_exec_state <= IDLE; end case; end if; end if; end process; --tvalid generation --axis_tvalid is asserted when the control state machine's state is SEND_STREAM and --number of output streaming data is less than the NUMBER_OF_OUTPUT_WORDS. axis_tvalid <= '1' when (mst_exec_state = SEND_STREAM) else '0'; -- AXI tlast generation -- axis_tlast is asserted number of output streaming data is NUMBER_OF_OUTPUT_WORDS-1 -- (0 to NUMBER_OF_OUTPUT_WORDS-1) axis_tlast <= '1' when (mst_exec_state = SEND_STREAM) else '0'; -- Delay the axis_tvalid and axis_tlast signal by one clock cycle -- to match the latency of M_AXIS_TDATA process(M_AXIS_ACLK) begin if (rising_edge (M_AXIS_ACLK)) then if(M_AXIS_ARESETN = '0') then axis_tvalid_delay <= '0'; axis_tlast_delay <= '0'; else axis_tvalid_delay <= axis_tvalid; axis_tlast_delay <= axis_tlast; end if; end if; end process; --FIFO read enable generation tx_en <= M_AXIS_TREADY and axis_tvalid; -- FIFO Implementation -- Latch the data from the serial interface into a register to be sent when ready. process(M_AXIS_ACLK) begin if rising_edge(M_AXIS_ACLK) then -- Latch in the sample when a rising edge is first detected. prev_i2s_done <= I2S_DONE; if ((I2S_DONE /= prev_i2s_done and I2S_DONE = '1') and I2S_LR_DONE = '0') then -- Sign extend the I2S sample before storing L_reg <= std_logic_vector(resize(signed(I2S_L_RECV), C_M_AXIS_TDATA_WIDTH)); data_ready <= '1'; elsif mst_exec_state = SEND_STREAM then data_ready <= '0'; end if; end if; end process; -- Streaming output data is read from FIFO process(M_AXIS_ACLK) begin if (rising_edge (M_AXIS_ACLK)) then if(M_AXIS_ARESETN = '0') then stream_data_out <= (others => '0'); tx_done <= '0'; elsif (tx_en = '1') then -- && M_AXIS_TSTRB(byte_index) stream_data_out <= L_reg; tx_done <= '1'; else tx_done <= '0'; end if; end if; end process; end implementation;