一,vivado工程配置
1,ZYNQ7 Processing System 中,HP Slave AXI Interface --> S AXI HP0 Interface,勾选 S AXI HP0 Interface 并且在展开的 AXI HP0 DATA WIDTH 后面选择数据位宽是 64(位宽可以配置为 32bit 或者64bit)。
2,按照如图引出来
3,在 Address Editor 中,由于新增加的 AXI_HP0 总线地址还未做映射,所以如图所示,点击左侧的 Auto Assign Address 进行自动地址分配。完成地址映射后,如图所示,AXI_HP0 默认分配了偏移地址(Offset Address)0x0 开始 的 1G 内存空间,这 1G 的地址空间是 AXI_HP0 可访问的地址空间。DDR3 也会默认映射到这一段地址空间中。通过 AXI_HP0 就可以实现 DDR3 的读写了。
二,PL端HP总线设置
上面配置是在PS端进行配置的,PL端也需要verilog HP总线进行数据读写
1,AXI HP总线,PL到PS端进行数据写设置:
`timescale 1 ns/10ps
module axi_hp0_wr(
//系统信号
input rst_n,
//写入DDR3的数据
input i_clk,
input i_data_rst_n,
input i_data_en,
input[15:0] i_data,
input[31:0] i_ddr3_saddr,
//AXI总线时钟
input AXI_clk,
//AXI写地址通道
(*mark_debug = "true"*) output reg[31:0] AXI_awaddr,
output[3:0] AXI_awlen,
output[2:0] AXI_awsize,
output[1:0] AXI_awburst,
output[1:0] AXI_awlock,
output[3:0] AXI_awcache,
output[2:0] AXI_awprot,
output[3:0] AXI_awqos,
(*mark_debug = "true"*) output reg AXI_awvalid,
(*mark_debug = "true"*) input AXI_awready,
//AXI写数据通道
(*mark_debug = "true"*) output[63:0] AXI_wdata,
output[7:0] AXI_wstrb,
(*mark_debug = "true"*) output reg AXI_wlast,
(*mark_debug = "true"*) output reg AXI_wvalid,
(*mark_debug = "true"*) input AXI_wready,
//AXI写响应通道
input[5:0] AXI_bid,
(*mark_debug = "true"*) input[1:0] AXI_bresp,
(*mark_debug = "true"*) input AXI_bvalid,
(*mark_debug = "true"*) output AXI_bready
);
//内部信号申明
reg fifo_rd_en;
wire[7:0] fifo_data_count;
reg[7:0] wrdata_num;
reg[3:0] cstate,nstate;
parameter AXI_BURST_LEN = 16;
parameter STATE_RST = 4'h0;
parameter STATE_IDLE = 4'h1;
parameter STATE_WADD = 4'h2;
parameter STATE_WDAT = 4'h3;
parameter WRITE_DONE = 4'h4;
//------------------------------------------------------------------------------------
//将i_data_rst_n在AXI_clk时钟域打一拍
reg w_data_rst_n;
always @(posedge AXI_clk)
w_data_rst_n <= i_data_rst_n;
//-------------------------------------------------------------------------------
//FIFO缓存写入DDR3数据
fifo_generator_0 uut_fifo_generator_0 (
.rst(~rst_n || ~w_data_rst_n), // input wire rst
.wr_clk(i_clk), // input wire wr_clk
.rd_clk(AXI_clk), // input wire rd_clk
.din(i_data), // input wire [15 : 0] din
.wr_en(i_data_en), // input wire wr_en
.rd_en(fifo_rd_en), // input wire rd_en
.dout({AXI_wdata[15:0],AXI_wdata[31:16],AXI_wdata[47:32],AXI_wdata[63:48]}), // output wire [63 : 0] dout
.full(), // output wire full
.empty(), // output wire empty
.rd_data_count(fifo_data_count) // output wire [7 : 0] rd_data_count
);
//-------------------------------------------------------------------------------
//AXI写状态机
always @(posedge AXI_clk or negedge rst_n)begin
if(~rst_n)begin
cstate <= STATE_RST;
end
else begin
cstate <= nstate;
end
end
always @( * )begin
case(cstate)
STATE_RST: begin
if(w_data_rst_n) nstate = STATE_IDLE;
else nstate = STATE_RST;
end
STATE_IDLE: begin
if(!w_data_rst_n) nstate = STATE_RST;
else if(fifo_data_count >= AXI_BURST_LEN) nstate = STATE_WADD;
else nstate = STATE_IDLE;
end
STATE_WADD: begin
if(AXI_awvalid && AXI_awready) nstate = STATE_WDAT;
else nstate = STATE_WADD;
end
STATE_WDAT: begin
if(wrdata_num >= (AXI_BURST_LEN+1)) nstate = WRITE_DONE;
else nstate = STATE_WDAT;
end
WRITE_DONE: begin
if(AXI_bvalid) nstate = STATE_IDLE;
else nstate = WRITE_DONE;
end
default: begin
nstate = STATE_RST;
end
endcase
end
//1个burst写入数据的个数计数
always @(posedge AXI_clk) begin
if (!rst_n) wrdata_num <= 'b0;
else if(cstate == STATE_WDAT) begin
if(wrdata_num == 8'd0) wrdata_num <= wrdata_num + 1'b1;
else if((wrdata_num <= AXI_BURST_LEN) && AXI_wready && AXI_wvalid) wrdata_num <= wrdata_num + 1'b1;
else wrdata_num <= wrdata_num;
end
else wrdata_num <= 'b0;
end
//-------------------------------------------------------------------------------
//FIFO读取时能信号产生
always @(*) begin
if (cstate == STATE_WDAT) begin
if(wrdata_num == 8'd0) fifo_rd_en <= 1'b1;
else if((wrdata_num >= 8'd1) && (wrdata_num < AXI_BURST_LEN) && AXI_wready && AXI_wvalid) fifo_rd_en <= 1'b1;
else fifo_rd_en <= 1'b0;
end
else fifo_rd_en <= 1'b0;
end
//-------------------------------------------------------------------------------
//AXI总线写数据时序产生
//写地址产生
always @(posedge AXI_clk)begin
if(!w_data_rst_n) AXI_awaddr <= i_ddr3_saddr;
else if(AXI_awvalid && AXI_awready) AXI_awaddr <= AXI_awaddr + AXI_BURST_LEN * 8;
end
//写地址有效信号产生
always @(posedge AXI_clk) begin
if (!rst_n) AXI_awvalid <= 1'b0;
else if(cstate == STATE_WADD) begin
if(AXI_awvalid && AXI_awready) AXI_awvalid <= 1'b0;
else AXI_awvalid <= 1'b1;
end
else AXI_awvalid <= 1'b0;
end
//写数据有效信号产生
always @(posedge AXI_clk) begin
if (!rst_n) AXI_wvalid <= 1'b0;
else if((wrdata_num >= 8'd1) && (wrdata_num < AXI_BURST_LEN)) AXI_wvalid <= 1'b1;
else if((wrdata_num == AXI_BURST_LEN) && !AXI_wready) AXI_wvalid <= 1'b1;
else AXI_wvalid <= 1'b0;
end
//写最后一个数据有效信号产生
always @(posedge AXI_clk) begin
if (!rst_n) AXI_wlast <= 1'b0;
else if((wrdata_num == (AXI_BURST_LEN - 1)) && AXI_wready && AXI_wvalid) AXI_wlast <= 1'b1;
else if((wrdata_num == AXI_BURST_LEN) && !AXI_wready) AXI_wlast <= 1'b1;
else AXI_wlast <= 1'b0;
end
assign AXI_awsize = 3'b011; //8 Bytes per burst
assign AXI_awburst = 2'b01;
assign AXI_awlock = 2'b00;
assign AXI_awcache = 4'b0010;
assign AXI_awprot = 3'h0;
assign AXI_awqos = 4'h0;
assign AXI_wstrb = 8'hff;
assign AXI_bready = 1'b1;
assign AXI_awlen = AXI_BURST_LEN - 1;
endmodule
其中fifo配置:
fifo_generator_0 uut_fifo_generator_0 (
.rst(~rst_n || ~w_data_rst_n), // input wire rst
.wr_clk(i_clk), // input wire wr_clk
.rd_clk(AXI_clk), // input wire rd_clk
.din(i_data), // input wire [15 : 0] din
.wr_en(i_data_en), // input wire wr_en
.rd_en(fifo_rd_en), // input wire rd_en
.dout({AXI_wdata[15:0],AXI_wdata[31:16],AXI_wdata[47:32],AXI_wdata[63:48]}),
.full(), // output wire full
.empty(), // output wire empty
.rd_data_count(fifo_data_count) // output wire [7 : 0] rd_data_count
);
2,AXI HP总线读取数据
`timescale 1 ns/10ps
module axi_hp0_rd(
//系统信号
input rst_n,
//写入DDR3的数据
input i_clk,
input o_data_rst_n,
input o_data_en,
input[31:0] o_ddr3_saddr,
//AXI总线时钟
input AXI_clk,
//AXI读地址通道
(*mark_debug = "true"*) output[31:0]AXI_araddr,
output[1:0] AXI_arburst,
output[3:0] AXI_arcache,
output[3:0] AXI_arlen,
output[1:0] AXI_arlock,
output[2:0] AXI_arprot,
output[3:0] AXI_arqos,
(*mark_debug = "true"*) input AXI_arready,
output[2:0] AXI_arsize,
(*mark_debug = "true"*) output AXI_arvalid,
//AXI读数据通道
(*mark_debug = "true"*) input[63:0] AXI_rdata,
input[5:0] AXI_rid,
(*mark_debug = "true"*) input AXI_rlast,
(*mark_debug = "true"*) output AXI_rready,
(*mark_debug = "true"*) input[1:0] AXI_rresp,
(*mark_debug = "true"*) input AXI_rvalid
);
parameter AXI_BURST_LEN = 16;
assign AXI_araddr = o_ddr3_saddr;
assign AXI_arvalid = o_data_en;
assign AXI_arsize = 3'b011; //8 Bytes per burst
assign AXI_arburst = 2'b01;
assign AXI_arlock = 2'b00;
assign AXI_arcache = 4'b0010;
assign AXI_arprot = 3'h0;
assign AXI_arqos = 4'h0;
assign AXI_rready = 1'b1;
assign AXI_arlen = AXI_BURST_LEN - 1;
endmodule
3,数据控制
`timescale 1 ns/10ps
module axi_hp0_source(
//系统信号
input rst_n,
input clk,
//读出DDR3的数据
output o_data_rst_n,
output reg o_data_en,
output [31:0] o_ddr3_saddr,
//写入DDR3的数据
output i_data_rst_n,
output reg i_data_en,
output reg[15:0] i_data,
output[31:0] i_ddr3_saddr
);
parameter MAX_CNT_1S = 32'd100_000_000-1; //1s计数最大值,时钟为100MHz(10ns)
//1s定时
reg[31:0] cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt <= 32'd0;
else if(cnt < MAX_CNT_1S) cnt <= cnt+1'b1;
else cnt <= 32'd0;
wire timer_wr_en = (cnt >= MAX_CNT_1S-1000) & (cnt < MAX_CNT_1S-1000+64);
assign i_data_rst_n = ~((cnt >= MAX_CNT_1S-10_000) & (cnt < MAX_CNT_1S-10_000+64));
wire timer_rd_en = (cnt == MAX_CNT_1S-10);
//------------------------------------------------------------------------------------
//产生定时数据写入
always @(posedge clk or negedge rst_n)
if(!rst_n) i_data_en <= 1'b0;
else i_data_en <= timer_wr_en;
always @(posedge clk or negedge rst_n)
if(!rst_n) i_data <= 16'd0;
else if(!i_data_rst_n) i_data <= 16'h0000;
else if(timer_wr_en) i_data <= i_data+1'b1;
assign i_ddr3_saddr = 32'h0100_0000;
//------------------------------------------------------------------------------------
//产生定时数据读取
always @(posedge clk or negedge rst_n)
if(!rst_n) o_data_en <= 1'b0;
else o_data_en <= timer_rd_en;
assign o_data_rst_n = i_data_rst_n;
assign o_ddr3_saddr = 32'h0100_0000;
endmodule
三,SDK下载触发验证和信号抓取: