如何实现axi_lite的双向传递

最近,由于项目。需要通过axi_lite实现PS与PL之间的双向信息传输。在网上找了好久,PS到PL单向传输的例子很多,比如http://www.eetop.cn/blog/html/70/1149070-51989.html这篇博文描述的这样。

而双向传输的例子却很难找到,通过阅读生成的自定义IP代码。发现PS有写寄存器的能力,也有读寄存器的能力。这就使得PL向PS传输信息可以实现。

本文后面贴出的代码,用最简单的方法来实现PL向PS的信息传输。将生成的代码中分配的四个寄存器中的最后一个寄存器PS写的能力禁止,只保存PS读的能力,而通过PL写这个寄存器(PS可读)来实现PL向PS传输信息。

接下来贴出修改部分代码:
首先,禁止PS对于最后一个寄存器写的能力。首先,要找到write logic部分,可通过查看生成代码注释找到。此部分代码如下所示(不同vivado版本可能有一定差异),对slv_reg3进行操作部分删除,本文代码采用注释方法方便比较,共三处,分别用(1)、(2)、(3)标记:

// Implement memory mapped register select and write logic generation
// The write data is accepted and written to memory mapped registers when
// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
// select byte enables of slave registers while writing.
// These registers are cleared when reset (active low) is applied.
// Slave register write enable is asserted when valid address and data are available
// and the slave is ready to accept the write address and write data.
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      slv_reg0 <= 0;
      slv_reg1 <= 0;
      slv_reg2 <= 0;
      //(1)// slv_reg3 <= 0;
    end 
  else begin
    if (slv_reg_wren)
      begin
        case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
          2'h0:
            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 0
                slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          2'h1:
            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 1
                slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          2'h2:
            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 2
                slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          //(2)//2'h3:
            //for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              //if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 3
                //slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          default : begin
                      slv_reg0 <= slv_reg0;
                      slv_reg1 <= slv_reg1;
                      slv_reg2 <= slv_reg2;
                     //(3)//slv_reg3 <= slv_reg3;
                    end
        endcase
      end
  end
end

在用户定义代码处加上如下代码:

// Add user logic here
always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      slv_reg3  <= 0;
    end 
  else
    begin
      slv_reg3 <= PL_data_in;       
    end
end
// User logic ends

当然,在输入端口处需要加上PL_data_in为输入端口。其他部分与单向情况类似。

你可能感兴趣的:(自定义IP核)