今天我做了如下实验axis stream data通过DMA S2MM写入DDRPS读取DDR并通过串口打印其中axis stream data的触发是通过按键完成并且在调试过程中发现一个有意思的问题即“我首先在SDK点击Debug包含program FPGA然后我又在vivado重新Program device出现了ila我设置了key_pressed1为trigger条件在SDK端点击Run之前我按了按键ila捕捉到source_tready在key_pressed1之前一直为高电平有效之后source_tready有效持续4个时钟周期然后又被拉低此时我返回SDK点击Run收到的是丢失前四个数据的结果。”该错误操作下的ila抓包结果如下再次运行debug并先在PS端启动DMA后进行按键启动数据传输ila抓包如下此时PS串口也输出了完整的8个数据。结论一定要确保axis stream data在source_tready真正有效之后再进行传输。其中PS端对DDR的配置和轮询程序如下#include xparameters.h #include xaxidma.h #include xil_printf.h #include xil_cache.h #include sleep.h #define DMA_DEV_ID XPAR_AXI_DMA_0_DEVICE_ID #define DDR_BUFFER_ADDR 0x10000000 #define TRANSFER_LENGTH 32 XAxiDma AxiDma; int main(void) { XAxiDma_Config *ConfigPtr; xil_printf(\r\n); xil_printf(----- AXI DMA S2MM Test -----\r\n); //1. 查找 DMA 配置 ConfigPtr XAxiDma_LookupConfig(DMA_DEV_ID); //2. 初始化 DMA XAxiDma_CfgInitialize(AxiDma, ConfigPtr); //3. 禁用 S2MM 中断当前我们采用轮询方式 XAxiDma_IntrDisable( AxiDma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA ); //4. 清空 DDR Buffer u32 *BufferPtr (u32 *)DDR_BUFFER_ADDR; for (int i 0; i 8; i) { BufferPtr[i] 0xAAAAAAAA; } // 5. Flush Cache Xil_DCacheFlushRange( DDR_BUFFER_ADDR, TRANSFER_LENGTH ); xil_printf(\r\n); xil_printf(DDR buffer initialized.\r\n); XAxiDma_SimpleTransfer( AxiDma, DDR_BUFFER_ADDR, TRANSFER_LENGTH, XAXIDMA_DEVICE_TO_DMA ); xil_printf(DMA S2MM is armed.\r\n); xil_printf(Please press KEY to start PL data transmission.\r\n); // 6. 等待 DMA 接收完成 while (XAxiDma_Busy( AxiDma, XAXIDMA_DEVICE_TO_DMA )) {;} xil_printf(DMA transfer completed.\r\n); // 7. Invalidate Cache Xil_DCacheInvalidateRange( DDR_BUFFER_ADDR, TRANSFER_LENGTH ); // 8. 读取 DDR xil_printf(\r\n); xil_printf(DDR data:\r\n); for (int i 0; i 8; i) { xil_printf( DDR[%d] 0x%08lx\r\n, i, BufferPtr[i] ); } xil_printf(\r\n); xil_printf(----- Test Finished -----\r\n); return XST_SUCCESS; }PL中有一部分关于ILA的使用需要注意这里我将自己的source文件作为RTL module加入到了block design中了ila_0 不要作为一个独立 OOC 子设计处理而是跟 pll_clock_top 一起综合。module pll_clock_top( input clk, input rstn, input key, output [3:0] leds, output source_tvalid, output source_tlast, output [31:0]source_tdata, output [3:0] source_tkeep, input source_tready, //output key_pressed, //input start //input start ); // // Key debounce // wire key_state,key_pressed,key_released; key_debounce inst_key_debounce( .clk(clk), .rstn(rstn), .key(key), .key_state(key_state), .key_pressed(key_pressed), .key_released(key_released) ); // // LED // led_blink inst_led_blink( .clk(clk), .rstn(rstn), .key_pressed(key_pressed), .leds(leds) ); assign source_tkeep4b1111; axis_test_source inst_axis_test_source( .clk(clk), .rstn(rstn), .start(key_pressed), .m_tdata(source_tdata), .m_tvalid(source_tvalid), .m_tlast(source_tlast), .m_tready(source_tready) ); //set_property generate_synth_checkpoint 0 [get_files ila_0.xci] //这样告诉 Vivadoila_0 不要作为一个独立 OOC 子设计处理而是跟 pll_clock_top 一起综合。 ila_0 your_instance_name ( .clk(clk), // input wire clk .probe0(key_pressed), // input wire [0:0] probe0 .probe1(source_tvalid), // input wire [0:0] probe1 .probe2(source_tlast), // input wire [0:0] probe2 .probe3(source_tready), // input wire [0:0] probe3 .probe4(source_tdata) // input wire [31:0] probe4 ); endmodule