You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Zynq的数据路由:DDR至自定义IP再存SD卡的VHDL连接问题

Alright, let's tackle this step by step—you've got the right blocks in place, now it's just about wiring them up correctly in VHDL to get that data flowing from Zynq DDR → custom IP → EMIO-connected SD card. Here's how to approach each connection:

1. Establish the PS DDR to PL Data Path (AXI DMA MM2S)

First, you need to link the Zynq PS's DDR to the AXI DMA's memory-mapped (MM) side. This uses the PS's high-performance AXI HP ports for fast data transfer:

  • Connect the DMA's M_AXI_MM2S interface to one of the Zynq PS's S_AXI_HP ports (e.g., HP0) — this is the path for reading data from DDR into the PL.
  • Connect the DMA's S_AXI_LITE interface to the PS's M_AXI_GP port (e.g., GP0) — this lets the PS configure the DMA (set transfer lengths, trigger transfers, etc.).

If you're writing VHDL manually (not using Vivado IP Integrator), make sure all AXI MM signals (address, data, valid/ready handshakes, write strobes) are correctly mapped between the PS and DMA.

2. AXI DMA to AXI Stream FIFO to Custom IP

Next, route the stream data from the DMA to your custom IP, using the AXI Stream FIFO as a buffer to prevent underruns/overruns:

  • The DMA's M_AXIS_MM2S (AXI Stream output) connects directly to the FIFO's S_AXIS (AXI Stream input).
  • The FIFO's M_AXIS (AXI Stream output) connects to your custom IP's AXI Stream input port.

Here's a simplified VHDL snippet for this connection (assuming a single clock domain):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity data_path is
    Port ( clk          : in  STD_LOGIC;
           resetn       : in  STD_LOGIC;
           -- DMA MM2S Signals
           dma_m_axis_tvalid : in  STD_LOGIC;
           dma_m_axis_tdata  : in  STD_LOGIC_VECTOR(31 downto 0);
           dma_m_axis_tlast  : in  STD_LOGIC;
           dma_m_axis_tready : out STD_LOGIC;
           -- Stream FIFO S_AXIS Signals
           fifo_s_axis_tvalid : out STD_LOGIC;
           fifo_s_axis_tdata  : out STD_LOGIC_VECTOR(31 downto 0);
           fifo_s_axis_tlast  : out STD_LOGIC;
           fifo_s_axis_tready : in  STD_LOGIC;
           -- Stream FIFO M_AXIS Signals
           fifo_m_axis_tvalid : in  STD_LOGIC;
           fifo_m_axis_tdata  : in  STD_LOGIC_VECTOR(31 downto 0);
           fifo_m_axis_tlast  : in  STD_LOGIC;
           fifo_m_axis_tready : out STD_LOGIC;
           -- Custom IP S_AXIS Signals
           custom_ip_tvalid : out STD_LOGIC;
           custom_ip_tdata  : out STD_LOGIC_VECTOR(31 downto 0);
           custom_ip_tlast  : out STD_LOGIC;
           custom_ip_tready : in  STD_LOGIC);
end data_path;

architecture Behavioral of data_path is
begin
    -- DMA MM2S to Stream FIFO
    process(clk, resetn)
    begin
        if resetn = '0' then
            fifo_s_axis_tvalid <= '0';
            fifo_s_axis_tdata  <= (others => '0');
            fifo_s_axis_tlast  <= '0';
        elsif rising_edge(clk) then
            fifo_s_axis_tvalid <= dma_m_axis_tvalid;
            fifo_s_axis_tdata  <= dma_m_axis_tdata;
            fifo_s_axis_tlast  <= dma_m_axis_tlast;
        end if;
    end process;
    dma_m_axis_tready <= fifo_s_axis_tready;

    -- Stream FIFO to Custom IP
    process(clk, resetn)
    begin
        if resetn = '0' then
            custom_ip_tvalid <= '0';
            custom_ip_tdata  <= (others => '0');
            custom_ip_tlast  <= '0';
        elsif rising_edge(clk) then
            custom_ip_tvalid <= fifo_m_axis_tvalid;
            custom_ip_tdata  <= fifo_m_axis_tdata;
            custom_ip_tlast  <= fifo_m_axis_tlast;
        end if;
    end process;
    fifo_m_axis_tready <= custom_ip_tready;
end Behavioral;
3. Custom IP Output to BRAM (If Using Intermediate Buffering)

If you need to buffer processed data in BRAM before sending it to the SD card, connect your custom IP to the BRAM controller and generator:

  • If your custom IP uses AXI Stream, you'll need an AXI Stream to AXI MM converter (like Xilinx's axis_to_mm IP) to interface with the BRAM controller's S_AXI port.
  • Wire the BRAM controller's BRAM signals (bram_addr, bram_wrdata, bram_en, bram_we) directly to the BRAM generator's corresponding ports.

Example VHDL snippet for BRAM controller to generator:

-- BRAM Controller to BRAM Generator
bram_gen_addr    <= bram_ctrl_bram_addr;
bram_gen_wrdata  <= bram_ctrl_bram_wrdata;
bram_gen_en      <= bram_ctrl_bram_en;
bram_gen_we      <= bram_ctrl_bram_we;
bram_ctrl_bram_rddata <= bram_gen_rddata;
4. Connect to EMIO SD Card

Finally, route the processed data to the SD card connected via EMIO:

  1. Add Xilinx's SD/SDIO Controller IP to your design.
  2. Connect the processed data (from custom IP or BRAM) to the SD controller's AXI interface:
    • If using BRAM, use an AXI DMA in S2MM mode to transfer data from BRAM to the SD controller's S_AXI port.
    • If sending directly from the custom IP, use an AXI Stream to AXI MM converter if needed.
  3. In the Zynq PS configuration, map the SD controller's pins (CLK, CMD, DAT0-DAT3) to EMIO pins (assign specific EMIO numbers to each SD signal).
  4. On the PS side, initialize the SD card via software (using Petalinux or Xilinx SDK) to enable the PL-based controller to write data.
Key Things to Remember
  • Clock/Reset Synchronization: All PL components must operate on the same clock domain (use an AXI Stream Data FIFO for cross-clock domain transfers if needed), and reset signals must be synchronized to the active clock.
  • AXI Protocol Compliance: Always follow AXI handshake rules (e.g., tvalid must stay high until tready is asserted for Stream interfaces; AXI MM address/data valid signals must wait for ready signals).
  • SD Card Initialization: Don't skip the PS-side software initialization—this sets up the SD card for use with the PL controller.

内容的提问来源于stack exchange,提问作者EE_minor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:21:34