在zynq上用xillybus实现PL与PS上的linux系统间的数据传输

1 xillybus介绍

  • xillybus是由Xilinx的合作伙伴xillybus推出的用于在FPGA和主机间进行数据传输的解决方案。在FPGA端通过标准FIFO与用户逻辑相连接,在主机端(Window或Linux)安装了相应的驱动程序后,可以以读写设备的方式接收数据或发送数据。本文主要介绍Linux系统下的数据传输。
    在这里插入图片描述
    在这里插入图片描述
  • xillybus有三种数据传输的方案。第一是通过PCIE实现FPGA和外部PC主机间数据的传输。第二是通过转接ZYNQ的ACP、HP、GP接口实现FPGA和PS间数据的传输。第三是通过地址映射Lite的方式实现FPGA和PS间的数据传输。

2 用户接口信号

2.1 DMA方式

  • 时钟:所有连到xillybus IP核的模块时钟都要用bus_clk驱动,PCIE平台根据最大链路带宽有62.5 MHz,125MHz,250 MHz,ZYNQ平台为100MHz。与用户逻辑连接时要用异步FIFO进行跨时钟域处理。
  • user_w前缀为host到fpga端下行数据流,user_r前缀为fpga到host端上行数据流。
  • 下行数据流部分:
    user_w_devfile_data为host到fpga的数据。
    user_w_devfile_wren为xillybus给fifo的写有效信号,指示data上的数据有效。
    user_w_devfile_full为fifo给xillybus的信号,指示fifo已满。当该信号为低时,xillybus认为可以从host向fpga传输数据。
    user_w_devfile_open信号当host端进行open系统调用打开设备时,该信号有效。
  • 上行数据流部分:
    user_r_devfile_data为fpga到host的数据。
    user_r_devfile_rden为xillybus给fifo的读有效信号,拉高后,下个时钟时data开始上传数据。
    user_r_devfile_empty为fifo给xillybus的信号,指示fifo为空。
    user_r_devfile_eof为xillybus的输入信号,指示产生eof事件。一旦拉高,xillybus将不再读取输入数据,除非host关闭fd并再次打开。在host端read系统调用会返回eof。
    user_r_devfile_open为xillybus输出信号,指示host端已open。
  • quiesce

在这里插入图片描述

3 PL部分工程介绍

3.1 IP factory

  • 使用xillybus需要先在xillybus的官网根据需求配置数据传输通道的参数。ip factory网址
  • 我这里配置了一个上行通道、一个下行通道和一个双向通道,还配置了期望带宽,数据传输方式设置为异步传输。配置好后可生成对应的ngc网表文件,例化到vavado工程中即可。
    在这里插入图片描述

3.2 总线连接

  • blockdesign如下图所示,xillybus_ip_v1_0核和xillybus_lite_v1_0核挂接在zynq的GP总线上。这两个IP核都挂接在系统物理总线上,占用了一定的物理地址空间。我们在Address Editor中可以看到地址的分配情况,我们在后面导出的hdf文件中也描述了对这些地址空间的占用。
    在这里插入图片描述
  • xillybus_ip_v1_0核用于DMA方式的数据传输。xillybus_M_AXI是xillybus的主AXI接口,用于上行数据传输。xillybus_S_AXI是xillybus的从AXI接口,用于下行数据传输。xillybus_bus_clk和xillybus_bus_rst_n是IP核输出的控制ngc部分的时钟和复位信号。xillybus_host_interrupt是用户主机的中断信号。
  • xillybus_lite_v1_0核用于LITE方式的数据传输。
    在这里插入图片描述

3.3 例化ngc

  • xillybus_core模块中例化了ngc网表文件,将xillybus_M_AXI和xillybus_S_AXI协议按照用户在IP factory中的配置进行转换,转换成用户配置的指定通道的接口信号。lite与xillybus_core无关。
 xillybus_core  xillybus_core_ins(
    .S_AXI_AWADDR_w(S_AXI_AWADDR), 
	.S_AXI_AWVALID_w(S_AXI_AWVALID),
    .S_AXI_WDATA_w(S_AXI_WDATA), 
    .S_AXI_WSTRB_w(S_AXI_WSTRB), 
	.S_AXI_WVALID_w(S_AXI_WVALID),
    .S_AXI_BREADY_w(S_AXI_BREADY), 
	.S_AXI_ARADDR_w(S_AXI_ARADDR),
    .S_AXI_ARVALID_w(S_AXI_ARVALID), 
	.S_AXI_RREADY_w(S_AXI_RREADY),
    .S_AXI_ARREADY_w(S_AXI_ARREADY), 
	.S_AXI_RDATA_w(S_AXI_RDATA),
    .S_AXI_RRESP_w(S_AXI_RRESP), 
	.S_AXI_RVALID_w(S_AXI_RVALID),
    .S_AXI_WREADY_w(S_AXI_WREADY), 
	.S_AXI_BRESP_w(S_AXI_BRESP),
    .S_AXI_BVALID_w(S_AXI_BVALID), 
	.S_AXI_AWREADY_w(S_AXI_AWREADY),
	
    .M_AXI_ACP_ARREADY_w(M_AXI_ACP_ARREADY), 
	.M_AXI_ACP_ARVALID_w(M_AXI_ACP_ARVALID),
    .M_AXI_ACP_ARADDR_w(M_AXI_ACP_ARADDR), 
	.M_AXI_ACP_ARLEN_w(M_AXI_ACP_ARLEN),
    .M_AXI_ACP_ARSIZE_w(M_AXI_ACP_ARSIZE), 
	.M_AXI_ACP_ARBURST_w(M_AXI_ACP_ARBURST),
    .M_AXI_ACP_ARPROT_w(M_AXI_ACP_ARPROT), 
	.M_AXI_ACP_ARCACHE_w(M_AXI_ACP_ARCACHE),
    .M_AXI_ACP_RREADY_w(M_AXI_ACP_RREADY), 
	.M_AXI_ACP_RVALID_w(M_AXI_ACP_RVALID),
    .M_AXI_ACP_RDATA_w(M_AXI_ACP_RDATA), 
	.M_AXI_ACP_RRESP_w(M_AXI_ACP_RRESP), 
    .M_AXI_ACP_RLAST_w(M_AXI_ACP_RLAST), 
	.M_AXI_ACP_AWREADY_w(M_AXI_ACP_AWREADY),
    .M_AXI_ACP_AWVALID_w(M_AXI_ACP_AWVALID), 
	.M_AXI_ACP_AWADDR_w(M_AXI_ACP_AWADDR),
    .M_AXI_ACP_AWLEN_w(M_AXI_ACP_AWLEN), 
	.M_AXI_ACP_AWSIZE_w(M_AXI_ACP_AWSIZE),
	.M_AXI_ACP_AWBURST_w(M_AXI_ACP_AWBURST), 
    .M_AXI_ACP_AWPROT_w(M_AXI_ACP_AWPROT), 
	.M_AXI_ACP_AWCACHE_w(M_AXI_ACP_AWCACHE),
    .M_AXI_ACP_WREADY_w(M_AXI_ACP_WREADY), 
	.M_AXI_ACP_WVALID_w(M_AXI_ACP_WVALID),
    .M_AXI_ACP_WDATA_w(M_AXI_ACP_WDATA), 
	.M_AXI_ACP_WSTRB_w(M_AXI_ACP_WSTRB),
    .M_AXI_ACP_WLAST_w(M_AXI_ACP_WLAST), 
	.M_AXI_ACP_BREADY_w(M_AXI_ACP_BREADY),
    .M_AXI_ACP_BVALID_w(M_AXI_ACP_BVALID), 
	.M_AXI_ACP_BRESP_w(M_AXI_ACP_BRESP),

	.bus_clk_w(bus_clk), 
	.bus_rst_n_w(bus_rst_n),
	.host_interrupt_w(host_interrupt),
	.quiesce_w(quiesce),
	.GPIO_LED_w(GPIO_LED), 
	
	.user_r_channel_1_rden_w(user_r_channel_1_rden),
    .user_r_channel_1_data_w(user_r_channel_1_data),
    .user_r_channel_1_empty_w(user_r_channel_1_empty),
    .user_r_channel_1_eof_w(user_r_channel_1_eof),
	.user_r_channel_1_open_w(user_r_channel_1_open),
    .user_w_channel_1_wren_w(user_w_channel_1_wren),
    .user_w_channel_1_data_w(user_w_channel_1_data),
    .user_w_channel_1_full_w(user_w_channel_1_full),
	.user_w_channel_1_open_w(user_w_channel_1_open),
	
    .user_r_channel_2_rden_w(user_r_channel_2_rden),
    .user_r_channel_2_data_w(user_r_channel_2_data),
    .user_r_channel_2_empty_w(user_r_channel_2_empty),
    .user_r_channel_2_eof_w(user_r_channel_2_eof),
    .user_r_channel_2_open_w(user_r_channel_2_open),
	
    .user_w_channel_3_wren_w(user_w_channel_3_wren),
    .user_w_channel_3_data_w(user_w_channel_3_data),
    .user_w_channel_3_full_w(user_w_channel_3_full),
    .user_w_channel_3_open_w(user_w_channel_3_open));

3.4 数据传输测试设计

  • DMA上行数据传输测试,FPGA端产生自增数,在PS端读取自增数后检验数据的正确性。用vio控制产生自增数的速率。
reg  [9:0]     count;
wire [9:0]    vio_output_value_channel_2;

assign user_r_channel_2_eof = 0;

vio_up_speed_control vio_up_speed_control_inst (
  .clk(clk_102p4MHz),               
  .probe_out0(vio_output_value_channel_2)  
);

/*	
     	count = 16     6.4MB
		count = 32    12.8MB	
		count = 64    25.6MB
*/
always@(posedge clk_102p4MHz) 
begin
	if(!rst_n)
			count <= 1'b0;
	else
			count <= count + 1'b1;
end			

always@(posedge clk_102p4MHz)
begin
	if(!rst_n)
		begin
			upstream_data        <= 32'b0;
			upstream_data_valid  <= 1'b0;
	    end
	else if(count <= vio_output_value_channel_2)
		begin
			upstream_data       <= upstream_data + 1'b1;
			upstream_data_valid <= 1'b1;
		end
	else
		begin
			upstream_data        <= upstream_data;
			upstream_data_valid  <= 1'b0;
		end
end		
  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值