1. 配置BD
配置GP master引出PS时钟复位
PL到PS中断
添加 AXI BRAM Controller ip
自动连线并引出使用的引脚。
2. 编写PL代码
module top_bram(
DDR_addr,
DDR_ba,
DDR_cas_n,
DDR_ck_n,
DDR_ck_p,
DDR_cke,
DDR_cs_n,
DDR_dm,
DDR_dq,
DDR_dqs_n,
DDR_dqs_p,
DDR_odt,
DDR_ras_n,
DDR_reset_n,
DDR_we_n,
FIXED_IO_ddr_vrn,
FIXED_IO_ddr_vrp,
FIXED_IO_mio,
FIXED_IO_ps_clk,
FIXED_IO_ps_porb,
FIXED_IO_ps_srstb
);
inout [14:0]DDR_addr;
inout [2:0]DDR_ba;
inout DDR_cas_n;
inout DDR_ck_n;
inout DDR_ck_p;
inout DDR_cke;
inout DDR_cs_n;
inout [3:0]DDR_dm;
inout [31:0]DDR_dq;
inout [3:0]DDR_dqs_n;
inout [3:0]DDR_dqs_p;
inout DDR_odt;
inout DDR_ras_n;
inout DDR_reset_n;
inout DDR_we_n;
inout FIXED_IO_ddr_vrn;
inout FIXED_IO_ddr_vrp;
inout [53:0]FIXED_IO_mio;
inout FIXED_IO_ps_clk;
inout FIXED_IO_ps_porb;
inout FIXED_IO_ps_srstb;
wire [31:0]doutb;
wire [31:0]addrb;
wire [31:0]dinb;
wire [3:0]web;
wire pl_clk,pl_rstn;
wire IRQ_F2P_0;
Bram_rw Bram_rw_u(
.clk_bram(pl_clk),
.rst_n(pl_rstn),
.doutb(doutb),
.data(32'd1000), //要写入的数据
.addrb(addrb),
.dinb(dinb),
.web(web), //有效字节
.IRQ_F2P_0(IRQ_F2P_0)
);
system_wrapper system_wrapper_u
(
.DDR_addr(DDR_addr),
.DDR_ba(DDR_ba),
.DDR_cas_n(DDR_cas_n),
.DDR_ck_n(DDR_ck_n),
.DDR_ck_p(DDR_ck_p),
.DDR_cke(DDR_cke),
.DDR_cs_n(DDR_cs_n),
.DDR_dm(DDR_dm),
.DDR_dq(DDR_dq),
.DDR_dqs_n(DDR_dqs_n),
.DDR_dqs_p(DDR_dqs_p),
.DDR_odt(DDR_odt),
.DDR_ras_n(DDR_ras_n),
.DDR_reset_n(DDR_reset_n),
.DDR_we_n(DDR_we_n),
.FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
.FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
.FIXED_IO_mio(FIXED_IO_mio),
.FIXED_IO_ps_clk(FIXED_IO_ps_clk),
.FIXED_IO_ps_porb(FIXED_IO_ps_porb),
.FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
.IRQ_F2P_0(IRQ_F2P_0),
.addrb_0(addrb),
.clkb_0(pl_clk),
.dinb_0(dinb),
.doutb_0(doutb),
.enb_0(1'b1),
.pl_clk(pl_clk),
.pl_rstn(pl_rstn),
.rstb_0(!pl_rstn),
.web_0(web)
);
endmodule
module Bram_rw(
input clk_bram,
input rst_n,
input [31:0]doutb,
input [31:0]data, //要写入的数据
output [31:0]addrb,
output reg [31:0]dinb ,
output reg [3:0] web, //有效字节
output reg IRQ_F2P_0
);
//PL写BRAM
// wire dinbValueVio = 32'd1000;//写入的数据的初始值
wire writeEnVio;//启动写数据
reg writeEnReg1;
reg wrState;
reg [31:0] addrbWrite;//写数据地址
//PL读BRAM
wire readEnVio;//启动读数据
reg readEnReg1;
reg rdState;
reg [31:0]addrbRead ;
wire rstb;
assign rstb = ~rst_n;
assign addrb = wrState?addrbWrite:rdState?addrbRead:32'd0;
/******pl wr bram*******/
/******pl wr bram*******/
/******pl wr bram*******/
always@(posedge clk_bram)begin
if(rstb)begin
writeEnReg1 <= 1'b0;
end
else begin
writeEnReg1 <= writeEnVio;
end
end
always@(posedge clk_bram)begin
if(rstb )begin
dinb <= 32'd0;
web <= 4'd0;
wrState <= 1'b0;
addrbWrite <= 32'd0;
end
else begin
case(wrState)
1'b0:
if(writeEnVio&~writeEnReg1)begin//边沿检测,检测到上升沿启动写过程
wrState <= 1'b1;
web <= 4'b1111;
addrbWrite <= 32'd0;
dinb <= data; //
end
else begin
wrState <= wrState;
web <= 4'd0;
addrbWrite <= 32'd0;
dinb <= 32'd0;
end
1'b1:
if(addrbWrite >= 32'd32)begin //写入9个数据0-32,每个数据32位
wrState <= 1'b0;
web <= 4'd0;
addrbWrite <= 32'd0;
dinb[31:0] <= 32'd0;
end
else begin
wrState <= wrState;
web <= web;
addrbWrite <= addrbWrite + 32'd4;
dinb <= dinb + 32'd1; //写入每个地址数据累加1
end
endcase
end
end
/******pl rd bram*******/
/******pl rd bram*******/
always@(posedge clk_bram)begin
if(rstb )begin
readEnReg1 <= 1'b0;
end
else begin
readEnReg1 <= readEnVio;
end
end
always@(posedge clk_bram)begin
if(rstb)begin
rdState <= 1'b0;
addrbRead <= 32'd0;
end
else begin
case(rdState)
1'b0:
if(readEnVio&~readEnReg1)begin
rdState <= 1'b1;
addrbRead <= 32'd0;
end else begin
rdState <= 1'b0;
addrbRead <= 32'd0;
end
1'b1:
if(addrbRead >= 32'd32)begin
rdState <= 1'd0;
end else begin
addrbRead <= addrbRead+ 32'd4;
rdState <= rdState;
end
endcase
end
end
vio_0 vio_0_u (
.clk(clk_bram), // input wire clk
.probe_out0(readEnVio), // output wire [0 : 0] probe_in0
.probe_out1(writeEnVio) // output wire [0 : 0] probe_in1
);
ila_0 ila_0_u (
.clk(clk_bram), // input wire clk
.probe0(addrb), // input wire [12:0] probe0
.probe1(doutb), // input wire [31:0] probe1
.probe2(dinb), // input wire [31:0] probe2
.probe3(web), // input wire [3:0] probe3
.probe4(wrState), // input wire [0:0] probe4
.probe5(rdState) // input wire [0:0] probe5
);
//PL到PS中断
reg wrStateEnd;
always@(posedge clk_bram)begin
if(rstb)
wrStateEnd <= 1'b0;
else
wrStateEnd <= wrState;
end
always@(posedge clk_bram)begin
if(rstb)
IRQ_F2P_0 <= 1'b0;
else if(wrStateEnd & (!wrState))
IRQ_F2P_0 <= 1'b1;
else
IRQ_F2P_0 <= 1'b0;
end
endmodule
module system_wrapper
(DDR_addr,
DDR_ba,
DDR_cas_n,
DDR_ck_n,
DDR_ck_p,
DDR_cke,
DDR_cs_n,
DDR_dm,
DDR_dq,
DDR_dqs_n,
DDR_dqs_p,
DDR_odt,
DDR_ras_n,
DDR_reset_n,
DDR_we_n,
FIXED_IO_ddr_vrn,
FIXED_IO_ddr_vrp,
FIXED_IO_mio,
FIXED_IO_ps_clk,
FIXED_IO_ps_porb,
FIXED_IO_ps_srstb,
IRQ_F2P_0,
addrb_0,
clkb_0,
dinb_0,
doutb_0,
enb_0,
pl_clk,
pl_rstn,
rstb_0,
web_0);
inout [14:0]DDR_addr;
inout [2:0]DDR_ba;
inout DDR_cas_n;
inout DDR_ck_n;
inout DDR_ck_p;
inout DDR_cke;
inout DDR_cs_n;
inout [3:0]DDR_dm;
inout [31:0]DDR_dq;
inout [3:0]DDR_dqs_n;
inout [3:0]DDR_dqs_p;
inout DDR_odt;
inout DDR_ras_n;
inout DDR_reset_n;
inout DDR_we_n;
inout FIXED_IO_ddr_vrn;
inout FIXED_IO_ddr_vrp;
inout [53:0]FIXED_IO_mio;
inout FIXED_IO_ps_clk;
inout FIXED_IO_ps_porb;
inout FIXED_IO_ps_srstb;
input [0:0]IRQ_F2P_0;
input [31:0]addrb_0;
input clkb_0;
input [31:0]dinb_0;
output [31:0]doutb_0;
input enb_0;
output pl_clk;
output [0:0]pl_rstn;
input rstb_0;
input [3:0]web_0;
wire [14:0]DDR_addr;
wire [2:0]DDR_ba;
wire DDR_cas_n;
wire DDR_ck_n;
wire DDR_ck_p;
wire DDR_cke;
wire DDR_cs_n;
wire [3:0]DDR_dm;
wire [31:0]DDR_dq;
wire [3:0]DDR_dqs_n;
wire [3:0]DDR_dqs_p;
wire DDR_odt;
wire DDR_ras_n;
wire DDR_reset_n;
wire DDR_we_n;
wire FIXED_IO_ddr_vrn;
wire FIXED_IO_ddr_vrp;
wire [53:0]FIXED_IO_mio;
wire FIXED_IO_ps_clk;
wire FIXED_IO_ps_porb;
wire FIXED_IO_ps_srstb;
wire [0:0]IRQ_F2P_0;
wire [31:0]addrb_0;
wire clkb_0;
wire [31:0]dinb_0;
wire [31:0]doutb_0;
wire enb_0;
wire pl_clk;
wire [0:0]pl_rstn;
wire rstb_0;
wire [3:0]web_0;
system system_i
(.DDR_addr(DDR_addr),
.DDR_ba(DDR_ba),
.DDR_cas_n(DDR_cas_n),
.DDR_ck_n(DDR_ck_n),
.DDR_ck_p(DDR_ck_p),
.DDR_cke(DDR_cke),
.DDR_cs_n(DDR_cs_n),
.DDR_dm(DDR_dm),
.DDR_dq(DDR_dq),
.DDR_dqs_n(DDR_dqs_n),
.DDR_dqs_p(DDR_dqs_p),
.DDR_odt(DDR_odt),
.DDR_ras_n(DDR_ras_n),
.DDR_reset_n(DDR_reset_n),
.DDR_we_n(DDR_we_n),
.FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
.FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
.FIXED_IO_mio(FIXED_IO_mio),
.FIXED_IO_ps_clk(FIXED_IO_ps_clk),
.FIXED_IO_ps_porb(FIXED_IO_ps_porb),
.FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
.IRQ_F2P_0(IRQ_F2P_0),
.addrb_0(addrb_0),
.clkb_0(clkb_0),
.dinb_0(dinb_0),
.doutb_0(doutb_0),
.enb_0(enb_0),
.pl_clk(pl_clk),
.pl_rstn(pl_rstn),
.rstb_0(rstb_0),
.web_0(web_0));
endmodule
3. PS端代码
往BRAM地址写入数据
Xil_Out32(BRAM_ADDR + 4i,dataIn);
读出数据
dataOut[i] = Xil_In32(BRAM_ADDR + 4i);
DEBUG模式查看内存是否写入成功
ILA和VIO操作PL侧读写
PS端中断回调函数里读出数据。