当前位置:   article > 正文

xdma axi-stream 回环测试_xdma stream read

xdma stream read

rk3588 上测试通过

xdma 回环

建立一个xdma axi stream的ip后,然后生成示例工程,示例工程就能用
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 配置

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

msix一定要,不然各种超时
在这里插入图片描述
在这里插入图片描述


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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/976460
推荐阅读
相关标签
  

闽ICP备14008679号