最近,由于项目。需要通过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为输入端口。其他部分与单向情况类似。