UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor lmaziere
Visitor
411 Views
Registered: ‎05-30-2018

Add an AXI4-Stream IP in a native RTL project

Jump to solution

Hi,

I created a video IP using Vivado HLS 2018.3. It has AXI4-Stream data interfaces.

This IP works correctly when added to a block design (Vivado 2018.3)

It receives AXI4-Stream input video and transfers it to a VDMA without error.

Now, I want to include my IP in a block design free project which has no AXI4-Stream communication at all.

My idea was to create a custom module to emulate a AXI4-Stream protocol given that I know hsize and vsize. Here's my code:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.std_logic_unsigned.ALL;

entity data_to_axis_v2_0_M00_AXIS is
	generic (
		-- Users to add parameters here
		-- 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 number of clock cycles the master will wait before initiating/issuing any transaction.
		C_M_START_COUNT	: integer := 32
	);
	port (
		-- Users to add ports here
        dataIn          : in STD_LOGIC_VECTOR (C_M_AXIS_TDATA_WIDTH-1 downto 0);
        M_AXIS_TUSER	: out std_logic_vector(0 downto 0);
        HSIZE           : in std_logic_vector(31 downto 0);
        VSIZE           : in std_logic_vector(31 downto 0);
		-- 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);
		-- TSTRB is the byte qualifier that indicates whether the content of the associated byte of TDATA is processed as a data byte or a position byte.
		M_AXIS_TSTRB	: out std_logic_vector((C_M_AXIS_TDATA_WIDTH/8)-1 downto 0);
		-- TLAST indicates the boundary of a packet.
		M_AXIS_TLAST	: out std_logic;
		-- TREADY indicates that the slave can accept a transfer in the current cycle.
		M_AXIS_TREADY	: in std_logic
	);
end data_to_axis_v2_0_M00_AXIS;

architecture implementation of data_to_axis_v2_0_M00_AXIS is

	-- Total number of output data        
	signal i_hsize : integer;       
	signal i_vsize : integer;       
    signal NUMBER_OF_IMAGE_DATA : integer;

	-- AXIS
	signal axis_tvalid : std_logic;
	signal axis_tdata : std_logic_vector(C_M_AXIS_TDATA_WIDTH-1 downto 0);
	signal axis_tlast : std_logic;
	signal axis_tuser : std_logic_vector(0 downto 0);

	-- Data counters
	signal line_counter : unsigned(31 downto 0);
	signal data_counter : unsigned(31 downto 0);
	
	-- Reset counter
	signal reset_counter : unsigned(7 downto 0);
	signal reset_disabled : std_logic;


begin
    -- Integer values
    i_hsize <= to_integer(unsigned(HSIZE));
    i_vsize <= to_integer(unsigned(VSIZE));
    NUMBER_OF_IMAGE_DATA <= i_hsize*i_vsize;
    
	-- I/O Connections assignments
	M_AXIS_TVALID	<= axis_tvalid;
	M_AXIS_TDATA	<= axis_tdata;
	M_AXIS_TLAST	<= axis_tlast;
	M_AXIS_TUSER	<= axis_tuser;
	M_AXIS_TSTRB	<= (others => '1');
	
    -- TDATA
    tdata_p: process(M_AXIS_ACLK)
    begin
        if (rising_edge(M_AXIS_ACLK)) then
            if (M_AXIS_ARESETN = '0') then
                axis_tdata <= (others => '0');
            else
                if ((axis_tvalid='1') and (M_AXIS_TREADY='1')) then
                    axis_tdata <= dataIn;
                end if;			
            end if;
        end if;
    end process tdata_p;
	
	-- Count number of cycles after reset
	reset_p: process (M_AXIS_ACLK)
	begin
        if (rising_edge(M_AXIS_ACLK)) then
            if (M_AXIS_ARESETN = '0') then
                reset_disabled <= '0';
                reset_counter <= (others => '0');
            else
                reset_counter <= reset_counter + 1;
                
                if (reset_counter = C_M_START_COUNT) then
                    reset_disabled <= '1';
                end if;
            end if;
        end if;
	end process reset_p;
	
	-- TVALID
	tvalid_p: process(M_AXIS_ACLK)
	begin
        if (rising_edge(M_AXIS_ACLK)) then
            if (M_AXIS_ARESETN = '0') then
                axis_tvalid <= '0';
            else
                if (reset_disabled = '1') then
                    axis_tvalid <= '1';
                end if;
            end if;
        end if;
	end process tvalid_p;
	
	-- TLAST and TUSER
	tlast_tuser_p: process(M_AXIS_ACLK)
	begin
        if (rising_edge(M_AXIS_ACLK)) then
            if (M_AXIS_ARESETN = '0') then
                line_counter <= (others => '1');
                data_counter <= (others => '1');
            else
                if ((axis_tvalid='1') and (M_AXIS_TREADY='1')) then
                    if (data_counter = NUMBER_OF_IMAGE_DATA - 2) then
                        data_counter <= (others => '1');
                        axis_tuser <= (others => '1');
                    else
                        data_counter <= data_counter + 1;
                        axis_tuser <= (others => '0');
                    end if;
                    
                    if (line_counter = i_hsize - 2) then
                        line_counter <= (others => '1');
                        axis_tlast <= '1';
                    else
                        line_counter <= line_counter + 1;
                        axis_tlast <= '0';
                    end if;
                end if;			
            end if;
        end if;
	end process tlast_tuser_p;
	

end implementation;

I have two major issues:

  1. I need to feed this module with hsize*2 instead of hsize to have an entire image on the output of the processing IP (VHLS)
  2. It seems like I have missing data / missing lines (see images, the shift is normal)

input.pnginput image before custom AXI4-Stream moduleoutput.pngoutput image after VHLS IP

Where should I look?

Thanks,

 

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
Visitor lmaziere
Visitor
303 Views
Registered: ‎05-30-2018

Re: Add an AXI4-Stream IP in a native RTL project

Jump to solution

Hi everyone,

Problem solved!

I had to take into account hsync and vsync to say when my pixel is valid.

It's quite similar to what you said @dgisselq about blanking ;)

Thanks

 

View solution in original post

0 Kudos
3 Replies
Moderator
Moderator
321 Views
Registered: ‎11-09-2015

Re: Add an AXI4-Stream IP in a native RTL project

Jump to solution

Hi @lmaziere 

You might want to check the output value of you IP using an ILA to check it is correct.

If this is correct, you might want to check if you processor is not using the same memory region as the one use by your VDMA. You can do this in you linker script. I have done (and explained) this in my Video Series 24: Using the AXI VDMA in Triple Buffer Mode.

Regards


Florent
Product Application Engineer - Xilinx Technical Support EMEA
**~ Don't forget to reply, give kudos, and accept as solution.~**
0 Kudos
Scholar dgisselq
Scholar
311 Views
Registered: ‎05-21-2015

Re: Add an AXI4-Stream IP in a native RTL project

Jump to solution

@lmaziere,

I noticed that you accept a new piece of data on every clock cycle, and that there's really no way for the downstream video generator to tell your upstream pixel generator that its generating a pixel during a blanking interval.  Your logic only uses the TREADY line for this purpose, yet does nothing to communicate teh TREADY information upstream.

I might suggest you rethink your approach.

If it helps at all, you can find an open source video example here that doesn't use block design at all.  It does include a simulator, so that you can see the image as its being created on a window on your screen, as well as then being able to see a full trace of everything going on within the design.  You can read about it more here if you are interested.  The example is for VGA, although I do have some HDMI examples lying around as well.

Dan

Visitor lmaziere
Visitor
304 Views
Registered: ‎05-30-2018

Re: Add an AXI4-Stream IP in a native RTL project

Jump to solution

Hi everyone,

Problem solved!

I had to take into account hsync and vsync to say when my pixel is valid.

It's quite similar to what you said @dgisselq about blanking ;)

Thanks

 

View solution in original post

0 Kudos