• xdma axi-stream


    xdma 回环

    vivado 里有官方示例
    fpga:pcie rx – axi-stream master – axi-stream slave – pcie tx
    流程:电脑启动读取,然后电脑再在超时时间内写入。或者电脑启动写入,然后电脑再在超时时间内读出。只读取或只写入会报超时,所以需要双线程进行
    细节:只有电脑启动读取,pcie tx – axi-stream slave 才会使能 ready 信号,然后 pcie rx – axi-stream master 才能向 pcie tx – axi-stream slave 写数据


    pcie xdma 配置

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述


    verilog hdl

    work.v:

    module work #(
        parameter C_DATA_WIDTH = 64
    ) (
        // AXI streaming
        output wire [C_DATA_WIDTH-1:0]   s_axis_c2h_tdata_0,  
        output wire                      s_axis_c2h_tlast_0,
        output wire                      s_axis_c2h_tvalid_0,
        input  wire                      s_axis_c2h_tready_0,
        output wire [C_DATA_WIDTH/8-1:0] s_axis_c2h_tkeep_0,
        input  wire [C_DATA_WIDTH-1:0]   m_axis_h2c_tdata_0,
        input  wire                      m_axis_h2c_tlast_0,
        input  wire                      m_axis_h2c_tvalid_0,
        output wire                      m_axis_h2c_tready_0,
        input  wire [C_DATA_WIDTH/8-1:0] m_axis_h2c_tkeep_0,
    
        // clk、rst
        input  wire sys_rst_n,
        input  wire user_resetn,
        input  wire user_clk,
        input  wire user_lnk_up,
    
        // led
        output wire [3:0] leds
    );
    
    reg [25:0] user_clk_heartbeat;
    
    assign sys_resetn = sys_rst_n;
    
    // led
    assign leds[0] = sys_resetn;
    assign leds[1] = user_resetn;
    assign leds[2] = user_lnk_up;
    assign leds[3] = user_clk_heartbeat[25];
    
    // AXI streaming
    assign s_axis_c2h_tdata_0  = m_axis_h2c_tdata_0;
    assign s_axis_c2h_tlast_0  = 0;
    assign s_axis_c2h_tvalid_0 = m_axis_h2c_tvalid_0;
    assign s_axis_c2h_tkeep_0  = m_axis_h2c_tkeep_0; // 如果每次都凑够 64bit 就可以直接等于 8'hff
    assign m_axis_h2c_tready_0 = s_axis_c2h_tready_0;
    
    // led blink
    always @(posedge user_clk) begin
        if(!sys_resetn) begin
            user_clk_heartbeat <= 26'd0;
        end else begin
            user_clk_heartbeat <= user_clk_heartbeat + 1'b1;
        end
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    main.v:

    module main #(
        parameter PL_LINK_CAP_MAX_LINK_WIDTH = 2, // 1- X1; 2 - X2; 4 - X4; 8 - X8
        parameter C_DATA_WIDTH               = 64
    ) (
        // pcie
        output [(PL_LINK_CAP_MAX_LINK_WIDTH - 1) : 0] pci_exp_txp,
        output [(PL_LINK_CAP_MAX_LINK_WIDTH - 1) : 0] pci_exp_txn,
        input  [(PL_LINK_CAP_MAX_LINK_WIDTH - 1) : 0] pci_exp_rxp,
        input  [(PL_LINK_CAP_MAX_LINK_WIDTH - 1) : 0] pci_exp_rxn,
    
        // clk、rst
        input  sys_clk_p,
        input  sys_clk_n,
        input  sys_rst_n,
    
        // led
        output [3:0] leds
    );
    
    localparam C_NUM_USR_IRQ = 1;
    
    // pcie clk、rst
    wire sys_clk;
    wire sys_rst_n_c;
    
    IBUFDS_GTE2 refclk_ibuf (.O(sys_clk), .ODIV2(), .I(sys_clk_p), .CEB(1'b0), .IB(sys_clk_n));
    IBUF sys_reset_n_ibuf (.O(sys_rst_n_c), .I(sys_rst_n));
    
    // user
    wire user_lnk_up;
    wire user_clk;
    wire user_resetn;
    
    // irq
    reg  [C_NUM_USR_IRQ-1:0] usr_irq_req = 0;
    
    // AXI streaming
    wire [C_DATA_WIDTH-1:0]	  m_axis_h2c_tdata_0;
    wire 			          m_axis_h2c_tlast_0;
    wire 			          m_axis_h2c_tvalid_0;
    wire 			          m_axis_h2c_tready_0;
    wire [C_DATA_WIDTH/8-1:0] m_axis_h2c_tkeep_0;
    wire [C_DATA_WIDTH-1:0]   s_axis_c2h_tdata_0; 
    wire                      s_axis_c2h_tlast_0;
    wire                      s_axis_c2h_tvalid_0;
    wire                      s_axis_c2h_tready_0;
    wire [C_DATA_WIDTH/8-1:0] s_axis_c2h_tkeep_0; 
    
    xdma_0 xdma_0_i (
        // clk、rst
        .sys_rst_n(sys_rst_n_c),
        .sys_clk  (sys_clk),
    
        // pcie
        .pci_exp_txn(pci_exp_txn),
        .pci_exp_txp(pci_exp_txp),
        .pci_exp_rxn(pci_exp_rxn),
        .pci_exp_rxp(pci_exp_rxp),
    
        // AXI streaming
        .s_axis_c2h_tdata_0 (s_axis_c2h_tdata_0),  
        .s_axis_c2h_tlast_0 (s_axis_c2h_tlast_0),
        .s_axis_c2h_tvalid_0(s_axis_c2h_tvalid_0), 
        .s_axis_c2h_tready_0(s_axis_c2h_tready_0),
        .s_axis_c2h_tkeep_0 (s_axis_c2h_tkeep_0),
        .m_axis_h2c_tdata_0 (m_axis_h2c_tdata_0),
        .m_axis_h2c_tlast_0 (m_axis_h2c_tlast_0),
        .m_axis_h2c_tvalid_0(m_axis_h2c_tvalid_0),
        .m_axis_h2c_tready_0(m_axis_h2c_tready_0),
        .m_axis_h2c_tkeep_0 (m_axis_h2c_tkeep_0),
    
        .axi_aclk   (user_clk),
        .axi_aresetn(user_resetn),
    
        // led
        .user_lnk_up(user_lnk_up),
    
        // irq
        .usr_irq_req(usr_irq_req),
        .usr_irq_ack(),
        .msix_enable(),
    );
    
    work #(
        .C_DATA_WIDTH(C_DATA_WIDTH)
    ) work_i (
        // AXI streaming
        .s_axis_c2h_tdata_0 (s_axis_c2h_tdata_0),  
        .s_axis_c2h_tlast_0 (s_axis_c2h_tlast_0),
        .s_axis_c2h_tvalid_0(s_axis_c2h_tvalid_0), 
        .s_axis_c2h_tready_0(s_axis_c2h_tready_0),
        .s_axis_c2h_tkeep_0 (s_axis_c2h_tkeep_0),
        .m_axis_h2c_tdata_0 (m_axis_h2c_tdata_0),
        .m_axis_h2c_tlast_0 (m_axis_h2c_tlast_0),
        .m_axis_h2c_tvalid_0(m_axis_h2c_tvalid_0),
        .m_axis_h2c_tready_0(m_axis_h2c_tready_0),
        .m_axis_h2c_tkeep_0 (m_axis_h2c_tkeep_0),
    
        // clk、rst
        .user_clk(user_clk),
        .user_resetn(user_resetn),
        .sys_rst_n(sys_rst_n_c),
        .user_lnk_up(user_lnk_up),
    
        // led
        .leds(leds)
    );
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109

    constr.xdc:
    led 高电平亮。正常情况下,板卡上电待 fpga 程序加载完毕后,第四个灯会一直闪烁,亮灭切换间隔大约为 500ms;第一个灯也会亮,等待约3秒钟就会灭然后等待约 500ms 第一、二、三号灯一起长亮

    ## configure
    set_property CFGBVS VCCO                         [current_design]
    set_property CONFIG_VOLTAGE 3.3                  [current_design]
    set_property CONFIG_MODE SPIx4                   [current_design]
    set_property BITSTREAM.CONFIG.CONFIGRATE 50      [current_design]
    set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4     [current_design]
    set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES  [current_design]
    set_property BITSTREAM.GENERAL.COMPRESS TRUE     [current_design]
    set_property BITSTREAM.CONFIG.UNUSEDPIN PULLNONE [current_design]
    
    ## pcie
    # clock
    set_property PACKAGE_PIN F6 [get_ports sys_clk_p]
    
    # data
    set_property PACKAGE_PIN D9  [get_ports {pci_exp_rxp[0]}]
    set_property PACKAGE_PIN B10 [get_ports {pci_exp_rxp[1]}]
    set_property PACKAGE_PIN D7  [get_ports {pci_exp_txp[0]}]
    set_property PACKAGE_PIN B6  [get_ports {pci_exp_txp[1]}]
    
    # rst
    set_property -dict {PACKAGE_PIN N15 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
    
    ## led
    set_property -dict {PACKAGE_PIN V9 IOSTANDARD LVCMOS15} [get_ports {leds[0]}]
    set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS15} [get_ports {leds[1]}]
    set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS15} [get_ports {leds[2]}]
    set_property -dict {PACKAGE_PIN W7 IOSTANDARD LVCMOS15} [get_ports {leds[3]}]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    linux 下 rust 测试 xdma stream 的回环

    main.rs:

    fn main() {
    	use rand::Rng;
    	use std::fs::OpenOptions;
    	use std::io::{Read, Write};
    	
    	let (read_tx, read_rx) = mpsc::channel();
    	
    	thread::spawn(move || {
    	    let mut buffer = vec![0u8; 200];
    	    let mut file = OpenOptions::new()
    	        .read(true)
    	        .open("/dev/xdma0_c2h_0")
    	        .unwrap();
    	    file.read(buffer.as_mut_slice()).unwrap();
    	
    	    read_tx.send(buffer).unwrap();
    	});
    	
    	thread::spawn(move || {
    	    let mut buffer = vec![0u8; 200];
    	    for index in 0..(buffer.len() / 2) {
    	        let rng: u16 = rand::thread_rng().gen_range(0..=1023);
    	        buffer[index * 2] = (rng >> 8) as u8;
    	        buffer[index * 2 + 1] = rng as u8;
    	    }
    	
    	    let mut file = OpenOptions::new()
    	        .write(true)
    	        .open("/dev/xdma0_h2c_0")
    	        .unwrap();
    	    file.write(buffer.as_slice()).unwrap();
    	});
    	
    	let buffer = read_rx.recv().unwrap();
    	let mut data = vec![0u16; 100];
    	for index in 0..(buffer.len() / 2) {
    	    data[index] = ((buffer[index * 2] as u16) << 8) | (buffer[index * 2 + 1] as u16);
    	}
    	printfln!("xdma: {}", data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    Cargo.toml:

    [dependencies]
    rand = "*"
    
    • 1
    • 2
  • 相关阅读:
    Python 操作redisearch
    Java中泛型——类型擦除
    数据同步到Redis消息队列,并实现消息发布/订阅
    超详细SSM框架实现增删改查功能项目整体流程
    Redis-企业级解决方案
    [Qt][C++]static与extern关键字
    解析nc格式文件,GRB格式文件的依赖包edu.ucar.netcdfAll的api 学习
    矢量图绘制软件EazyDraw mac中文版软件介绍
    Rust 从入门到精通09-模式解构
    ChatGPT4.0怎么收费
  • 原文地址:https://blog.csdn.net/qq_41544116/article/details/133826702