cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
t2_shashwat
Visitor
Visitor
860 Views
Registered: ‎04-28-2019

Unable to perform AXI handshake with custom AXIS IP

Greetings!

I wrote a simple Verilog code for adding 10 to our 32 bit input (Just to make sure data transaction is correct when sending data through SDK).  For that, we created an AXIS IP and integrated it with the blockdesign shown in this tutorial (http://www.fpgadeveloper.com/2017/11/creating-a-custom-axi-streaming-ip-in-vivado.html). I am not using the code that they provided for loopback and also not using the code xilinx generates when creating a custom AXI4 peripheral IP.

But when we are sending data to our IP through SDK we only get correct output for the first input. I am using simple_poll_example provided in SDK examples.

What I am thinking is that, this is due to incorrect AXI signal handshaking between IPs. Therefore the outputs are wrong.

Can you please give some clarity on integrating any Verilog module using AXI signals.

Thanks,

Shashwat 

0 Kudos
8 Replies
savula
Moderator
Moderator
795 Views
Registered: ‎10-30-2017

Hi @t2_shashwat ,

Could you please palce a system ILA in between AXI DMA and custom IP (M_AXIS_MM2S) and check the AXI handshaking. This will give confirm us whether the issue is with the AXI handshaking or something else. Basically in the AXI DMA polled mode example, the processor will Initialize the AXI DMA and reads the data from the ddr and write it to stream channel vice versa.

Best Regards,
Srikanth
----------------------------------------------------------------------------------------------
Kindly note- Please mark the Answer as "Accept as solution" if information provided is helpful.

Give Kudos to a post which you think is helpful and reply oriented.

0 Kudos
larshb
Adventurer
Adventurer
792 Views
Registered: ‎08-30-2018

This is a snippet from one of my AXI slaves. Although it is written in VHDL, it might give you some clarity if you see anything differing.

  sync: process (S_AXI_ACLK) begin
    if rising_edge(S_AXI_ACLK) then 
      if S_AXI_ARESETN = '0' then

        axi_awready <= '0';
        aw_en <= '1';
        axi_awaddr <= (others => '0');
        axi_wready <= '0';
        axi_bvalid  <= '0';
        axi_bresp   <= "00";
        axi_arready <= '0';
        axi_araddr  <= (others => '1');
        axi_rvalid <= '0';
        axi_rresp  <= "00";
        axi_rdata  <= (others => '0');

      else

        if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then
          axi_awready <= '1';
          aw_en <= '0';
        elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then
          aw_en <= '1';
          axi_awready <= '0';
        else
          axi_awready <= '0';
        end if;

        if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then
          axi_awaddr <= S_AXI_AWADDR;
        end if;

        if (axi_wready = '0' and S_AXI_WVALID = '1' and S_AXI_AWVALID = '1' and aw_en = '1') then
          axi_wready <= '1';
        else
          axi_wready <= '0';
        end if;

        if (axi_awready = '1' and S_AXI_AWVALID = '1' and axi_wready = '1' and S_AXI_WVALID = '1' and axi_bvalid = '0'  ) then
          axi_bvalid <= '1';
          axi_bresp  <= "00";
        elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then   --check if bready is asserted while bvalid is high)
          axi_bvalid <= '0';                                 -- (there is a possibility that bready is always asserted high)
        end if;

        if (axi_arready = '0' and S_AXI_ARVALID = '1') then
          axi_arready <= '1';
          axi_araddr  <= S_AXI_ARADDR;
        else
          axi_arready <= '0';
        end if;

        if (axi_arready = '1' and S_AXI_ARVALID = '1' and axi_rvalid = '0') then
          axi_rvalid <= '1';
          axi_rresp  <= "00"; -- 'OKAY' response
        elsif (axi_rvalid = '1' and S_AXI_RREADY = '1') then
          axi_rvalid <= '0';
        end if;

        if (slv_reg_rden = '1') then
          axi_rdata <= reg_data_out;     -- register read data
        end if;

      end if;
    end if;
  end process;

  slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid);
  slv_reg_wren <= axi_wready and S_AXI_WVALID and axi_awready and S_AXI_AWVALID;
0 Kudos
savula
Moderator
Moderator
752 Views
Registered: ‎10-30-2017

Hi @larshb ,

Strange, when I referred to fpga developer tutorial, I thouhgt that you are using AXI Stream Interface, but the code you have provide is for AXI4 Full/Lite interface. now the questions is how you are connected your AXI4 full/lite IP to the Zynq using AXI DMA and how you are using polled mode example. the polled mode example expects one the interface is stream, but for me it looks like both the memory mapped interfaces only. 

Coming to the hand shanking in vhdl code that you have provided looks in-correct to me. AWVALID and AWREADY are independent from WVALID. This dependency not required. Please check the AXI protocol specification guide for read and write channel dependencies.

Please refer this tutorial: http://www.fpgadeveloper.com/2014/08/creating-a-custom-ip-block-in-vivado.html


Best Regards,
Srikanth
----------------------------------------------------------------------------------------------
Kindly note- Please mark the Answer as "Accept as solution" if information provided is helpful.

Give Kudos to a post which you think is helpful and reply oriented

0 Kudos
dpaul24
Scholar
Scholar
745 Views
Registered: ‎08-07-2014

@t2_shashwat 

As pointed out above you should say what you need. AXIStream or AXI4.

An AXIStream is pretty much simple. If the tready is asserted, then you just make the tvalid high and at the same time start sending tdata. When the data ends just de-assert tlast.

If it is an AXI4 IP, I would first ascertain that my custom AXI4 IP is really AXI4 compliant before connecting it to the design sub-system. For this I either connect it to a pre-verified AXI4 master and do a quick functional verification or use an AXI4 BFM.

------------FPGA enthusiast------------
Consider giving "Kudos" if you like my answer. Please mark my post "Accept as solution" if my answer has solved your problem
Asking for solutions to problems via PM will be ignored.

0 Kudos
larshb
Adventurer
Adventurer
653 Views
Registered: ‎08-30-2018

Yes, that was a quick copy-paste of a memory-mapped AXI-slave. Not AXI-stream.
> Coming to the hand shanking in vhdl code that you have provided looks in-correct to me.
The transaction code is simply generated using Vivado and reducing the synchronous blocks and combinatorics to share the same clk/rst-process. If in fact this is incorrect, there might be a problem with the AXI-slave generator-tool in Vivado (2018.3) itself.
0 Kudos
dgisselq
Scholar
Scholar
635 Views
Registered: ‎05-21-2015

This code is not AXI compliant.  It makes one of the more common and fundamental mistakes of AXI, checking for AxVALID && AxREADY && anything else.  You can read more about this bug here.

Dan

0 Kudos
larshb
Adventurer
Adventurer
492 Views
Registered: ‎08-30-2018

Thanks for letting me know. In any case that means the same flaw is present when generating AXI4 peripherals from the IP-packager.

0 Kudos
dgisselq
Scholar
Scholar
463 Views
Registered: ‎05-21-2015

@larshb,

Yes.  The IP packager generated code has been flawed since at least 2016.

Dan