AXI_HP接口
通过AXI_HP接口,可直接通过AXI_FULL协议向DDR中通过DMA传输数据。
BD设计
AXI_HP接口设置
AXI_Master代码
module axi_full_master #
(
parameter C_M_TARGET_SLAVE_BASE_ADDR = 32'h40000000,
parameter integer C_M_AXI_BURST_LEN = 16,
parameter integer C_M_AXI_ID_WIDTH = 1,
parameter integer C_M_AXI_ADDR_WIDTH = 32,
parameter integer C_M_AXI_DATA_WIDTH = 64,
parameter integer C_M_AXI_AWUSER_WIDTH = 0,
parameter integer C_M_AXI_ARUSER_WIDTH = 0,
parameter integer C_M_AXI_WUSER_WIDTH = 0,
parameter integer C_M_AXI_RUSER_WIDTH = 0,
parameter integer C_M_AXI_BUSER_WIDTH = 0
)
//编码测试
(
input wire M_AXI_ACLK ,
input wire M_AXI_ARESETN ,
output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_AWID ,
output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR ,
output wire [7 : 0] M_AXI_AWLEN ,
output wire [2 : 0] M_AXI_AWSIZE ,
output wire [1 : 0] M_AXI_AWBURST ,
output wire M_AXI_AWLOCK ,
output wire [3 : 0] M_AXI_AWCACHE ,
output wire [2 : 0] M_AXI_AWPROT ,
output wire [3 : 0] M_AXI_AWQOS ,
output wire [C_M_AXI_AWUSER_WIDTH-1 : 0] M_AXI_AWUSER ,
output wire M_AXI_AWVALID ,
input wire M_AXI_AWREADY ,
output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_WDATA ,
output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB ,
output wire M_AXI_WLAST ,
output wire [C_M_AXI_WUSER_WIDTH-1 : 0] M_AXI_WUSER ,
output wire M_AXI_WVALID ,
input wire M_AXI_WREADY ,
input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_BID ,
input wire [1 : 0] M_AXI_BRESP ,
input wire [C_M_AXI_BUSER_WIDTH-1 : 0] M_AXI_BUSER ,
input wire M_AXI_BVALID ,
output wire M_AXI_BREADY ,
output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_ARID ,
output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR ,
output wire [7 : 0] M_AXI_ARLEN ,
output wire [2 : 0] M_AXI_ARSIZE ,
output wire [1 : 0] M_AXI_ARBURST ,
output wire M_AXI_ARLOCK ,
output wire [3 : 0] M_AXI_ARCACHE ,
output wire [2 : 0] M_AXI_ARPROT ,
output wire [3 : 0] M_AXI_ARQOS ,
output wire [C_M_AXI_ARUSER_WIDTH-1 : 0] M_AXI_ARUSER ,
output wire M_AXI_ARVALID ,
input wire M_AXI_ARREADY ,
input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_RID ,
input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA ,
input wire [1 : 0] M_AXI_RRESP ,
input wire M_AXI_RLAST ,
input wire [C_M_AXI_RUSER_WIDTH-1 : 0] M_AXI_RUSER ,
input wire M_AXI_RVALID ,
output wire M_AXI_RREADY
);
function integer clogb2(input [4:0] data_width);
begin
for(clogb2 = 0;data_width > 0;clogb2 = clogb2 + 1)begin
data_width = data_width >> 1;
end
end
endfunction
/* parameter */
parameter P_BYTE_NUM_WIDTH = clogb2((C_M_AXI_DATA_WIDTH/8) - 1) ; //假设数据位宽64,7需要三个位宽表示
parameter P_BYTE_NUM = C_M_AXI_DATA_WIDTH/8 ;
/* output reg */
reg [C_M_AXI_ID_WIDTH-1 : 0] ro_M_AXI_AWID ;
reg [C_M_AXI_ADDR_WIDTH-1 : 0] ro_M_AXI_AWADDR ;
reg [7 : 0] ro_M_AXI_AWLEN ;
reg [2 : 0] ro_M_AXI_AWSIZE ;
reg [1 : 0] ro_M_AXI_AWBURST ;
reg ro_M_AXI_AWLOCK ;
reg [3 : 0] ro_M_AXI_AWCACHE ;
reg [2 : 0] ro_M_AXI_AWPROT ;
reg [3 : 0] ro_M_AXI_AWQOS ;
reg [C_M_AXI_AWUSER_WIDTH-1 : 0] ro_M_AXI_AWUSER ;
reg ro_M_AXI_AWVALID ;
reg [C_M_AXI_DATA_WIDTH-1 : 0] ro_M_AXI_WDATA ;
reg [C_M_AXI_DATA_WIDTH/8-1 : 0] ro_M_AXI_WSTRB ;
reg ro_M_AXI_WLAST ;
reg [C_M_AXI_WUSER_WIDTH-1 : 0] ro_M_AXI_WUSER ;
reg ro_M_AXI_WVALID ;
reg ro_M_AXI_BREADY ;
reg [C_M_AXI_ID_WIDTH-1 : 0] ro_M_AXI_ARID ;
reg [C_M_AXI_ADDR_WIDTH-1 : 0] ro_M_AXI_ARADDR ;
reg [7 : 0] ro_M_AXI_ARLEN ;
reg [2 : 0] ro_M_AXI_ARSIZE ;
reg [1 : 0] ro_M_AXI_ARBURST ;
reg ro_M_AXI_ARLOCK ;
reg [3 : 0] ro_M_AXI_ARCACHE ;
reg [2 : 0] ro_M_AXI_ARPROT ;
reg [3 : 0] ro_M_AXI_ARQOS ;
reg [C_M_AXI_ARUSER_WIDTH-1 : 0] ro_M_AXI_ARUSER ;
reg ro_M_AXI_ARVALID ;
reg ro_M_AXI_RREADY ;
/* input reg */
reg [C_M_AXI_DATA_WIDTH-1 : 0] ri_M_AXI_RDATA ;
/* user reg */
reg [7:0] write_cnt ;
reg [7:0] read_cnt ;
reg check_err ;
/* wire */
wire AW_action ;
wire W_action ;
wire WB_action ;
wire AR_action ;
wire R_action ;
assign M_AXI_AWID = ro_M_AXI_AWID ;
assign M_AXI_AWADDR = ro_M_AXI_AWADDR ;
assign M_AXI_AWLEN = ro_M_AXI_AWLEN ;
assign M_AXI_AWSIZE = ro_M_AXI_AWSIZE ;
assign M_AXI_AWBURST = ro_M_AXI_AWBURST ;
assign M_AXI_AWLOCK = ro_M_AXI_AWLOCK ;
assign M_AXI_AWCACHE = ro_M_AXI_AWCACHE ;
assign M_AXI_AWPROT = ro_M_AXI_AWPROT ;
assign M_AXI_AWQOS = ro_M_AXI_AWQOS ;
assign M_AXI_AWUSER = ro_M_AXI_AWUSER ;
assign M_AXI_AWVALID = ro_M_AXI_AWVALID ;
assign M_AXI_WDATA = ro_M_AXI_WDATA ;
assign M_AXI_WSTRB = ro_M_AXI_WSTRB ;
assign M_AXI_WLAST = ro_M_AXI_WLAST ;
assign M_AXI_WUSER = ro_M_AXI_WUSER ;
assign M_AXI_WVALID = ro_M_AXI_WVALID ;
assign M_AXI_BREADY = ro_M_AXI_BREADY ;
assign M_AXI_ARID = ro_M_AXI_ARID ;
assign M_AXI_ARADDR = ro_M_AXI_ARADDR ;
assign M_AXI_ARLEN = ro_M_AXI_ARLEN ;
assign M_AXI_ARSIZE = ro_M_AXI_ARSIZE ;
assign M_AXI_ARBURST = ro_M_AXI_ARBURST ;
assign M_AXI_ARLOCK = ro_M_AXI_ARLOCK ;
assign M_AXI_ARCACHE = ro_M_AXI_ARCACHE ;
assign M_AXI_ARPROT = ro_M_AXI_ARPROT ;
assign M_AXI_ARQOS = ro_M_AXI_ARQOS ;
assign M_AXI_ARUSER = ro_M_AXI_ARUSER ;
assign M_AXI_ARVALID = ro_M_AXI_ARVALID ;
assign M_AXI_RREADY = ro_M_AXI_RREADY ;
assign AW_action = M_AXI_AWVALID & M_AXI_AWREADY;
assign W_action = M_AXI_WVALID & M_AXI_WREADY ;
assign WB_action = M_AXI_BVALID & M_AXI_BREADY ;
assign AR_action = M_AXI_ARVALID & M_AXI_ARREADY;
assign R_action = M_AXI_RVALID & M_AXI_RREADY ;
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN) begin
ro_M_AXI_AWID <= 'd0;
ro_M_AXI_AWADDR <= C_M_TARGET_SLAVE_BASE_ADDR;
ro_M_AXI_AWLEN <= C_M_AXI_BURST_LEN - 1;
ro_M_AXI_AWSIZE <= P_BYTE_NUM_WIDTH;
ro_M_AXI_AWBURST <= 2'b01;
ro_M_AXI_AWLOCK <= 'd0;
ro_M_AXI_AWCACHE <= 'd2;
ro_M_AXI_AWPROT <= 'd0;
ro_M_AXI_AWQOS <= 'd0;
ro_M_AXI_AWUSER <= 'd0;
ro_M_AXI_AWVALID <= 'd1;
end
else if(AW_action) begin
ro_M_AXI_AWID <= 'd0;
ro_M_AXI_AWADDR <= 'd0;
ro_M_AXI_AWLEN <= 'd0;
ro_M_AXI_AWSIZE <= 'd0;
ro_M_AXI_AWBURST <= 'd0;
ro_M_AXI_AWLOCK <= 'd0;
ro_M_AXI_AWCACHE <= 'd0;
ro_M_AXI_AWPROT <= 'd0;
ro_M_AXI_AWQOS <= 'd0;
ro_M_AXI_AWUSER <= 'd0;
ro_M_AXI_AWVALID <= 'd0;
end
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
write_cnt <= 'd0;
else if(write_cnt == (C_M_AXI_BURST_LEN - 1) && W_action)
write_cnt <= 'd0;
else if(W_action)
write_cnt <= write_cnt + 1;
else
write_cnt <= write_cnt;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)begin
ro_M_AXI_WSTRB <= 'd0;
ro_M_AXI_WUSER <= 'd0;
ro_M_AXI_WVALID <= 'd0;
end
else if(M_AXI_WLAST)begin
ro_M_AXI_WSTRB <= 'd0;
ro_M_AXI_WUSER <= 'd0;
ro_M_AXI_WVALID <= 'd0;
end
else if(AW_action)begin
ro_M_AXI_WSTRB <= {P_BYTE_NUM{1'd1}};
ro_M_AXI_WUSER <= 'd0;
ro_M_AXI_WVALID <= 'd1;
end
else begin
ro_M_AXI_WSTRB <= ro_M_AXI_WSTRB ;
ro_M_AXI_WUSER <= ro_M_AXI_WUSER ;
ro_M_AXI_WVALID <= ro_M_AXI_WVALID;
end
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
ro_M_AXI_WDATA <= 'd0;
else if(M_AXI_WLAST && W_action)
ro_M_AXI_WDATA <= 'd0;
else if(W_action)
ro_M_AXI_WDATA <= ro_M_AXI_WDATA + 1;
else
ro_M_AXI_WDATA <= ro_M_AXI_WDATA;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
ro_M_AXI_WLAST <= 'd0;
else if(ro_M_AXI_WLAST && W_action)
ro_M_AXI_WLAST <= 'd0;
else if(write_cnt == (C_M_AXI_BURST_LEN - 2) && W_action)
ro_M_AXI_WLAST <= 'd1;
else
ro_M_AXI_WLAST <= ro_M_AXI_WLAST;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
ro_M_AXI_BREADY <= 'd0;
else if(WB_action)
ro_M_AXI_BREADY <= 'd0;
else if(ro_M_AXI_WLAST && W_action)
ro_M_AXI_BREADY <= 'd1;
else
ro_M_AXI_BREADY <= ro_M_AXI_BREADY;
end
/*
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)begin
ro_M_AXI_ARID <= 'd0 ;
ro_M_AXI_ARADDR <= 'd0 ;
ro_M_AXI_ARLEN <= 'd0 ;
ro_M_AXI_ARSIZE <= 'd0 ;
ro_M_AXI_ARBURST <= 'd0 ;
ro_M_AXI_ARLOCK <= 'd0 ;
ro_M_AXI_ARCACHE <= 'd0 ;
ro_M_AXI_ARPROT <= 'd0 ;
ro_M_AXI_ARQOS <= 'd0 ;
ro_M_AXI_ARUSER <= 'd0 ;
ro_M_AXI_ARVALID <= 'd0 ;
end
else if(AR_action)begin
ro_M_AXI_ARID <= 'd0 ;
ro_M_AXI_ARADDR <= 'd0 ;
ro_M_AXI_ARLEN <= 'd0 ;
ro_M_AXI_ARSIZE <= 'd0 ;
ro_M_AXI_ARBURST <= 'd0 ;
ro_M_AXI_ARLOCK <= 'd0 ;
ro_M_AXI_ARCACHE <= 'd0 ;
ro_M_AXI_ARPROT <= 'd0 ;
ro_M_AXI_ARQOS <= 'd0 ;
ro_M_AXI_ARUSER <= 'd0 ;
ro_M_AXI_ARVALID <= 'd0 ;
end
else if(WB_action)begin
ro_M_AXI_ARID <= 'd0 ;
ro_M_AXI_ARADDR <= C_M_TARGET_SLAVE_BASE_ADDR ;
ro_M_AXI_ARLEN <= C_M_AXI_BURST_LEN - 1;
ro_M_AXI_ARSIZE <= P_BYTE_NUM_WIDTH ;
ro_M_AXI_ARBURST <= 2'b01 ;
ro_M_AXI_ARLOCK <= 'd0 ;
ro_M_AXI_ARCACHE <= 4'd2 ;
ro_M_AXI_ARPROT <= 'd0 ;
ro_M_AXI_ARQOS <= 'd0 ;
ro_M_AXI_ARUSER <= 'd0 ;
ro_M_AXI_ARVALID <= 'd1 ;
end
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
ro_M_AXI_RREADY <= 'd0;
else if(M_AXI_RLAST && R_action)
ro_M_AXI_RREADY <= 'd0;
else if(AR_action)
ro_M_AXI_RREADY <= 'd1;
else
ro_M_AXI_RREADY <= ro_M_AXI_RREADY;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
read_cnt <= 'd0;
else if(M_AXI_RLAST && R_action)
read_cnt <= 'd0;
else if(R_action)
read_cnt <= read_cnt + 1;
else
read_cnt <= read_cnt;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if(!M_AXI_ARESETN)
check_err <= 'd0;
else if(R_action)begin
if(read_cnt != M_AXI_RDATA)
check_err <= 'd1;
end
else
check_err <= 'd0;
end
*/
endmodule
注意顶层中必须把Axi_Master模块数据位宽,突发长度,基址,SIZE设置对应好
在PS中进行读:
#include "xparameters.h"
#include "xil_io.h"
#include "xil_cache.h"
int main()
{
u64 data[16];
int i;
Xil_DCacheDisable();
Xil_ICacheDisable();
while(1){
for(i=0;i<16;i++)
data[i] = Xil_In64(XPAR_PS7_RAM_0_S_AXI_BASEADDR + i*8);
}
return 0;
}
读出的数据正确