赞
踩
在 rk3588 上测试通过
建立一个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 写数据
msix一定要,不然各种超时
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
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
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]}]
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); }
Cargo.toml:
[dependencies]
rand = "*"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。