(1)写FIFO和读FIFO的配置
(2)AXI接口写入控制代码:
module axi_master_write
(
//全局变量
input wire ACLK , //全局时钟
input wire ARESETN , //全局复位
//写地址通道变量
output wire [3:0] M_AXI_AWID , //写地址ID 用来标志一组写信号
output wire [31:0] M_AXI_AWADDR , //写地址 给出一次写突发传输的写地址
output wire [7:0] M_AXI_AWLEN , //突出长度 给出突出传输的次数
output wire [2:0] M_AXI_AWSIZE , //突出大小 给出每次突发传输的字节数
output wire [1:0] M_AXI_AWBURAST , //突出类型
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 , //质量服务QOS
output wire M_AXI_AWVALID , //有效信号,表明此通道的地址控制信号有效
input wire M_AXI_AWREADY , //表明从机可以接收地址和对应的控制信号
//写数据通道变量
output wire [63:0] M_AXI_WDATA , //写数据
output wire [7:0] M_AXI_WSTRB , //写数据有效的字节数
output wire M_AXI_WLAST , //表明此次传输是最后一个突发传输
output wire M_AXI_WVALID , //写有效信号,表明此次写有效
input wire M_AXI_WREADY , //表明从机可以接收写数据
//写响应通道变量
input wire [3:0] M_AXI_BID , //写响应ID TAG
input wire [1:0] M_AXI_BRESP , //写响应,表明写传输的状态
input wire M_AXI_BVALID , //写响应有效
output wire M_AXI_BREADY , //表明主机能够接收写响应
//用户端接口变量
input wire WR_START , //写突出触发信号
input wire [31:0] WR_ADDR , //地址
input wire [7:0] WR_LEN , //长度
output wire WR_READY , //写空闲
output wire WR_FIFO_RE , //连接到fifo的读使能
input wire [63:0] WR_FIFO_DATA , //连接到fifo的读数据
output wire WR_BURAST_FINISH //完成最后一次突发
);
reg [6:0] WR_STATE ;
reg [31:0] awaddr_reg ;
reg [7:0] awlen_reg ;
reg awvalid_reg ;
reg wvalid_reg ;
localparam S0_WR_IDLE = 7'b000_0001; //写空闲
localparam S1_WR_WAIT = 7'b000_0010; //写地址等待
localparam S2_WR_ADDR = 7'b000_0100; //写地址
localparam S3_WD_WAIT = 7'b000_1000; //写数据等待
localparam S4_WD_PROC = 7'b001_0000; //写数据循环
localparam S5_WR_RES = 7'b010_0000; //接收写应答
localparam S6_WR_DONE = 7'b100_0000; //写结束
//输出信号赋值
assign M_AXI_AWID = 4'b1111 ;
assign M_AXI_AWADDR = awaddr_reg ;
assign M_AXI_AWLEN = WR_LEN - 8'd1 ;
assign M_AXI_AWSIZE = 3'b011 ; //8字节,64位
assign M_AXI_AWBURAST = 2'b01 ;
assign M_AXI_AWLOCK = 1'd0 ;
assign M_AXI_AWCACHE = 4'b0010 ;
assign M_AXI_AWPROT = 3'b000 ;
assign M_AXI_AWQOS = 4'b0000 ;
assign M_AXI_AWVALID = awvalid_reg ;
assign M_AXI_WDATA = WR_FIFO_DATA ;
assign M_AXI_WSTRB = 8'b1111_1111 ;
assign M_AXI_WLAST = (awlen_reg == 8'd0);
assign M_AXI_WVALID = wvalid_reg ;
assign M_AXI_BREADY = M_AXI_BVALID ;
assign WR_READY = (WR_STATE == S0_WR_IDLE);
assign WR_FIFO_RE = (M_AXI_WVALID & M_AXI_WREADY);
assign WR_BURAST_FINISH = (WR_STATE == S6_WR_DONE);
//状态机设计
always@(posedge ACLK or negedge ARESETN)
if(!ARESETN)begin
WR_STATE <= S0_WR_IDLE;
awaddr_reg <= 32'd0;
awlen_reg <= 8'd0;
awvalid_reg <= 1'd0;
wvalid_reg <= 1'd0;
end
else begin
case(WR_STATE)
S0_WR_IDLE :begin
awlen_reg <= 8'd0;
awvalid_reg <= 1'd0;
wvalid_reg <= 1'd0;
if(WR_START == 1'd1)begin
WR_STATE <= S1_WR_WAIT;
awaddr_reg <= WR_ADDR;
end
end
S1_WR_WAIT :begin
WR_STATE <= S2_WR_ADDR;
end
S2_WR_ADDR :begin
WR_STATE <= S3_WD_WAIT;
awvalid_reg <= 1'd1;
wvalid_reg <= 1'd1;
end
S3_WD_WAIT :begin
if(M_AXI_AWREADY == 1'd1)begin
WR_STATE <= S4_WD_PROC;
awvalid_reg <= 1'd0;
awlen_reg <= WR_LEN - 8'd1;
end
end
S4_WD_PROC :begin
if(M_AXI_WREADY == 1'd1)begin
if(M_AXI_WLAST == 1'd1)begin
WR_STATE <= S5_WR_RES;
wvalid_reg <= 1'd0;
end
else begin
awlen_reg <= awlen_reg - 8'd1;
WR_STATE <= WR_STATE;
end
end
end
S5_WR_RES :begin
if(M_AXI_BVALID)begin
WR_STATE <= S6_WR_DONE;
end
end
S6_WR_DONE :begin
WR_STATE <= S0_WR_IDLE;
end
default:WR_STATE <= S0_WR_IDLE;
endcase
end
endmodule
(3)AXI接口读出控制代码:
module axi_master_read
(
//全局变量
input wire ACLK , //全局时钟
input wire ARESETN , //全局复位
//读地址通道变量
output wire [3:0] M_AXI_ARID ,
output wire [31:0] M_AXI_ARADDR ,
output wire [7:0] M_AXI_ARLEN ,
output wire [2:0] M_AXI_ARSIZE ,
output wire [1:0] M_AXI_ARBURAST ,
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 M_AXI_ARVALID ,
input wire M_AXI_ARREADY ,
//读数据通道变量
input wire [3:0] M_AXI_RID ,
input wire [63:0] M_AXI_RDATA ,
input wire [7:0] M_AXI_RSTRB ,
input wire M_AXI_RLAST ,
input wire M_AXI_RVALID ,
output wire M_AXI_RREADY ,
//用户端接口变量
input wire RD_START ,
input wire [31:0] RD_ADDR ,
input wire [7:0] RD_LEN ,
output wire RD_READY ,
output wire RD_FIFO_RE ,
output wire [63:0] RD_FIFO_DATA ,
output wire RD_BURAST_FINISH
);
reg [5:0] RD_STATE ;
reg [31:0] araddr_reg ;
reg arvalid_reg ;
localparam S0_RA_IDLE = 6'b00_0001;
localparam S1_RA_WAIT = 6'b00_0010;
localparam S2_RA_ADDR = 6'b00_0100;
localparam S3_RD_WAIT = 6'b00_1000;
localparam S4_RD_PROC = 6'b01_0000;
localparam S5_RD_DONE = 6'b10_0000;
//输出信号赋值
assign M_AXI_ARID = 4'b1111 ;
assign M_AXI_ARADDR = araddr_reg ;
assign M_AXI_ARLEN = RD_LEN - 8'd1 ;
assign M_AXI_ARSIZE = 3'b011 ; //8字节,64位
assign M_AXI_ARBURAST = 2'b01 ;
assign M_AXI_ARLOCK = 1'd0 ;
assign M_AXI_ARCACHE = 4'b0010 ;
assign M_AXI_ARPROT = 3'b000 ;
assign M_AXI_ARQOS = 4'b0000 ;
assign M_AXI_ARVALID = arvalid_reg ;
assign M_AXI_RREADY = M_AXI_RVALID ;
assign RD_READY = (RD_STATE == S0_RA_IDLE);
assign RD_FIFO_RE = M_AXI_RVALID ;
assign RD_FIFO_DATA = M_AXI_RDATA ;
assign RD_BURAST_FINISH = (RD_STATE == S5_RD_DONE);
//状态机设计
always@(posedge ACLK or negedge ARESETN)
if(!ARESETN)begin
RD_STATE <= S0_RA_IDLE;
araddr_reg <= 32'd0;
arvalid_reg <= 1'd0;
end
else begin
case(RD_STATE)
S0_RA_IDLE :begin
arvalid_reg <= 1'd0;
if(RD_START == 1'd1)begin
RD_STATE <= S1_RA_WAIT;
araddr_reg <= RD_ADDR;
end
end
S1_RA_WAIT :begin
RD_STATE <= S2_RA_ADDR;
end
S2_RA_ADDR :begin
RD_STATE <= S3_RD_WAIT;
arvalid_reg <= 1'd1;
end
S3_RD_WAIT :begin
if(M_AXI_ARREADY == 1'd1)begin
RD_STATE <= S4_RD_PROC;
arvalid_reg <= 1'd0;
end
end
S4_RD_PROC :begin
if(M_AXI_RREADY == 1'd1)begin
if(M_AXI_RLAST == 1'd1)begin
RD_STATE <= S5_RD_DONE;
end
end
end
S5_RD_DONE :begin
RD_STATE <= S0_RA_IDLE;
end
default:RD_STATE <= S0_RA_IDLE;
endcase
end
endmodule
(4)AXI接口读写控制模块:
module axi_ctrl
(
input wire ui_clk ,
input wire ui_rst ,
input wire pingpang ,
//写FIFO
input wire [31:0] wr_b_addr ,
input wire [31:0] wr_e_addr ,
input wire wr_clk ,
input wire data_wren ,
input wire [63:0] data_wr ,
input wire wr_rst ,
//读FIFO
input wire [31:0] rd_b_addr ,
input wire [31:0] rd_e_addr ,
input wire rd_clk ,
input wire data_rden ,
output wire [63:0] data_rd ,
input wire rd_rst ,
input wire read_enable ,
output wire rd_data_valid ,
//DDR3写
output wire wr_burst_req ,
output wire [31:0] wr_burst_addr ,
output wire [7:0] wr_burst_len ,
input wire wr_ready ,
input wire wr_fifo_re ,
output wire [63:0] wr_fifo_data ,
input wire wr_burst_finish ,
//DDR3读
output wire rd_burst_req ,
output wire [31:0] rd_burst_addr ,
output wire [7:0] rd_burst_len ,
input wire rd_ready ,
input wire rd_fifo_wr ,
input wire [63:0] rd_fifo_data ,
input wire rd_burst_finish
);
parameter MAX_DDR_WR_LEN = 128 ;
parameter MAX_DDR_RD_LEN = 128 ;
reg wr_burst_req_reg ;
reg [31:0] wr_burst_addr_reg ;
reg rd_burst_req_reg ;
reg [31:0] rd_burst_addr_reg ;
reg pingpang_reg ;
//写fifo
wire wr_fifo_wr_clk ;
wire wr_fifo_wr_rst ;
wire wr_fifo_rd_clk ;
wire wr_fifo_rd_rst ;
wire [15:0] wr_fifo_din ;
wire wr_fifo_wr_en ;
wire wr_fifo_rd_en ;
wire [63:0] wr_fifo_dout ;
wire wr_fifo_full ;
wire wr_fifo_almost_full ;
wire wr_fifo_empty ;
wire wr_fifo_almost_empty ;
wire [9:0] wr_fifo_rd_data_count ;
wire [11:0] wr_fifo_wr_data_count ;
//读fifo
wire rd_fifo_wr_clk ;
wire rd_fifo_wr_rst ;
wire rd_fifo_rd_clk ;
wire rd_fifo_rd_rst ;
wire [63:0] rd_fifo_din ;
wire rd_fifo_wr_en ;
wire rd_fifo_rd_en ;
wire [15:0] rd_fifo_dout ;
wire rd_fifo_full ;
wire rd_fifo_almost_full ;
wire rd_fifo_empty ;
wire rd_fifo_almost_empty ;
wire [11:0] rd_fifo_rd_data_count ;
wire [9:0] rd_fifo_wr_data_count ;
assign wr_burst_req = wr_burst_req_reg ;
assign wr_burst_addr= wr_burst_addr_reg ;
assign wr_burst_len = MAX_DDR_WR_LEN ;
assign wr_fifo_data = wr_fifo_dout ;
assign rd_burst_req = rd_burst_req_reg ;
assign rd_burst_addr= rd_burst_addr_reg ;
assign rd_burst_len = MAX_DDR_RD_LEN ;
assign data_rd = rd_fifo_dout;
assign rd_data_valid = !rd_fifo_empty;
assign wr_fifo_wr_clk = wr_clk ;
assign wr_fifo_wr_rst = ui_rst ;
assign wr_fifo_rd_clk = ui_clk ;
assign wr_fifo_rd_rst = ui_rst ;
assign wr_fifo_din = data_wr ;
assign wr_fifo_wr_en = data_wren ;
assign wr_fifo_rd_en = wr_fifo_re ;
assign rd_fifo_wr_clk = ui_clk ;
assign rd_fifo_wr_rst = ui_rst ;
assign rd_fifo_rd_clk = rd_clk ;
assign rd_fifo_rd_rst = ui_rst ;
assign rd_fifo_din = rd_fifo_data;
assign rd_fifo_wr_en = rd_fifo_wr ;
assign rd_fifo_rd_en = data_rden ;
always@(posedge ui_clk or posedge ui_rst)
if(ui_rst)
wr_burst_req_reg <= 1'd0;
else if(((wr_fifo_rd_data_count + 10'd2) >= MAX_DDR_WR_LEN) && wr_ready)
wr_burst_req_reg <= 1'd1;
else
wr_burst_req_reg <= 1'd0;
always@(posedge ui_clk or posedge ui_rst)
if(ui_rst)begin
wr_burst_addr_reg <= wr_b_addr;
pingpang_reg <= 1'd0;
end
else if(wr_burst_finish)begin
wr_burst_addr_reg <= wr_burst_addr_reg + (MAX_DDR_WR_LEN << 3);
if(pingpang == 1'd1)begin
if(wr_burst_addr_reg >= ((wr_e_addr << 1) - wr_b_addr - (MAX_DDR_WR_LEN << 3)))
wr_burst_addr_reg <= wr_b_addr;
if(wr_burst_addr_reg < wr_e_addr)
pingpang_reg <= 1'd0;
else
pingpang_reg <= 1'd1;
end
else begin
if(wr_burst_addr_reg >= wr_e_addr - (MAX_DDR_WR_LEN << 3))
wr_burst_addr_reg <= wr_b_addr;
end
end
else
wr_burst_addr_reg <= wr_burst_addr_reg;
always@(posedge ui_clk or posedge ui_rst)
if(ui_rst)
rd_burst_req_reg <= 1'd0;
else if((rd_fifo_wr_data_count <= (10'd1000 - MAX_DDR_RD_LEN)) && rd_ready && read_enable)
rd_burst_req_reg <= 1'd1;
else
rd_burst_req_reg <= 1'd0;
always@(posedge ui_clk or posedge ui_rst)
if(ui_rst)begin
if(pingpang == 1'd1)begin
rd_burst_addr_reg <= rd_e_addr;
end
else begin
rd_burst_addr_reg <= rd_b_addr;
end
end
else if(rd_burst_finish)begin
rd_burst_addr_reg <= rd_burst_addr_reg + (MAX_DDR_RD_LEN << 3);
if(pingpang == 1'd1)begin
if((rd_burst_addr_reg == (rd_b_addr - (MAX_DDR_RD_LEN << 3)))||
(rd_burst_addr_reg == ((rd_e_addr << 1) - rd_b_addr - (MAX_DDR_RD_LEN << 3))))begin
if(pingpang_reg)
rd_burst_addr_reg <= rd_b_addr;
else
rd_burst_addr_reg <= rd_e_addr;
end
end
else begin
if(rd_burst_addr_reg >= rd_e_addr - (MAX_DDR_RD_LEN << 3))
rd_burst_addr_reg <= rd_b_addr;
end
end
else
rd_burst_addr_reg <= rd_burst_addr_reg;
wr_fifo wr_fifo_inst
(
.wr_clk (wr_fifo_wr_clk ),
.wr_rst (wr_fifo_wr_rst ),
.rd_clk (wr_fifo_rd_clk ),
.rd_rst (wr_fifo_rd_rst ),
.din (wr_fifo_din ),
.wr_en (wr_fifo_wr_en ),
.rd_en (wr_fifo_rd_en ),
.dout (wr_fifo_dout ),
.full (wr_fifo_full ),
.almost_full (wr_fifo_almost_full ),
.empty (wr_fifo_empty ),
.almost_empty (wr_fifo_almost_empty ),
.rd_data_count (wr_fifo_rd_data_count ),
.wr_data_count (wr_fifo_wr_data_count )
);
rd_fifo rd_fifo_inst
(
.wr_clk (rd_fifo_wr_clk ),
.wr_rst (rd_fifo_wr_rst ),
.rd_clk (rd_fifo_rd_clk ),
.rd_rst (rd_fifo_rd_rst ),
.din (rd_fifo_din ),
.wr_en (rd_fifo_wr_en ),
.rd_en (rd_fifo_rd_en ),
.dout (rd_fifo_dout ),
.full (rd_fifo_full ),
.almost_full (rd_fifo_almost_full ),
.empty (rd_fifo_empty ),
.almost_empty (rd_fifo_almost_empty ),
.rd_data_count (rd_fifo_rd_data_count ),
.wr_data_count (rd_fifo_wr_data_count )
);
endmodule
(5)AXI接口顶层代码:
module axi_ddr3_top
(
input wire ddr3_clk ,
input wire reset_n ,
input wire pingpang ,
output wire ui_clk ,
output wire ui_rst ,
output wire init_calib_complete ,
//写FIFO
input wire [31:0] wr_b_addr ,
input wire [31:0] wr_e_addr ,
input wire wr_clk ,
input wire data_wren ,
input wire [63:0] data_wr ,
input wire wr_rst ,
//读FIFO
input wire [31:0] rd_b_addr ,
input wire [31:0] rd_e_addr ,
input wire rd_clk ,
input wire data_rden ,
output wire [63:0] data_rd ,
input wire rd_rst ,
input wire read_enable ,
output wire rd_data_valid ,
//DDR3物理接口
output wire ddr3_ck_n ,
output wire ddr3_ck_p ,
output wire ddr3_cke ,
output wire ddr3_reset_n ,
output wire [14:0] ddr3_addr ,
output wire [2:0] ddr3_ba ,
output wire ddr3_cs_n ,
output wire ddr3_cas_n ,
output wire ddr3_ras_n ,
output wire ddr3_odt ,
output wire ddr3_we_n ,
inout wire [31:0] ddr3_dq ,
inout wire [3:0] ddr3_dqs_n ,
inout wire [3:0] ddr3_dqs_p ,
output wire [3:0] ddr3_dm
);
//AXI写主机
wire wr_burst_req ;
wire [31:0] wr_burst_addr ;
wire [7:0] wr_burst_len ;
wire wr_ready ;
wire wr_fifo_re ;
wire [63:0] wr_fifo_data ;
wire wr_burst_finish ;
//AXI读主机
wire rd_burst_req ;
wire [31:0] rd_burst_addr ;
wire [7:0] rd_burst_len ;
wire rd_ready ;
wire rd_fifo_wr ;
wire [63:0] rd_fifo_data ;
wire rd_burst_finish ;
//写地址通道
wire [3:0] M_AXI_AWID ;
wire [31:0] M_AXI_AWADDR ;
wire [7:0] M_AXI_AWLEN ;
wire [2:0] M_AXI_AWSIZE ;
wire [1:0] M_AXI_AWBURAST ;
wire M_AXI_AWLOCK ;
wire [3:0] M_AXI_AWCACHE ;
wire [2:0] M_AXI_AWPROT ;
wire [3:0] M_AXI_AWQOS ;
wire M_AXI_AWVALID ;
wire M_AXI_AWREADY ;
//写数据通道
wire [63:0] M_AXI_WDATA ;
wire [7:0] M_AXI_WSTRB ;
wire M_AXI_WLAST ;
wire M_AXI_WVALID ;
wire M_AXI_WREADY ;
//写响应通道
wire [3:0] M_AXI_BID ;
wire [1:0] M_AXI_BRESP ;
wire M_AXI_BVALID ;
wire M_AXI_BREADY ;
//读地址通道
wire [3:0] M_AXI_ARID ;
wire [31:0] M_AXI_ARADDR ;
wire [7:0] M_AXI_ARLEN ;
wire [2:0] M_AXI_ARSIZE ;
wire [1:0] M_AXI_ARBURAST ;
wire M_AXI_ARLOCK ;
wire [3:0] M_AXI_ARCACHE ;
wire [2:0] M_AXI_ARPROT ;
wire [3:0] M_AXI_ARQOS ;
wire M_AXI_ARVALID ;
wire M_AXI_ARREADY ;
//读数据通道
wire [3:0] M_AXI_RID ;
wire [63:0] M_AXI_RDATA ;
wire [7:0] M_AXI_RSTRB ;
wire M_AXI_RLAST ;
wire M_AXI_RVALID ;
wire M_AXI_RREADY ;
axi_ctrl axi_ctrl_inst
(
.ui_clk (ui_clk ),
.ui_rst (ui_rst ),
.pingpang (pingpang ),
.wr_b_addr (wr_b_addr ),
.wr_e_addr (wr_e_addr ),
.wr_clk (wr_clk ),
.data_wren (data_wren ),
.data_wr (data_wr ),
.wr_rst (wr_rst ),
.rd_b_addr (rd_b_addr ),
.rd_e_addr (rd_e_addr ),
.rd_clk (rd_clk ),
.data_rden (data_rden ),
.data_rd (data_rd ),
.rd_rst (rd_rst ),
.read_enable (read_enable ),
.rd_data_valid (rd_data_valid ),
.wr_burst_req (wr_burst_req ),
.wr_burst_addr (wr_burst_addr ),
.wr_burst_len (wr_burst_len ),
.wr_ready (wr_ready ),
.wr_fifo_re (wr_fifo_re ),
.wr_fifo_data (wr_fifo_data ),
.wr_burst_finish (wr_burst_finish ),
.rd_burst_req (rd_burst_req ),
.rd_burst_addr (rd_burst_addr ),
.rd_burst_len (rd_burst_len ),
.rd_ready (rd_ready ),
.rd_fifo_wr (rd_fifo_wr ),
.rd_fifo_data (rd_fifo_data ),
.rd_burst_finish (rd_burst_finish )
);
axi_master_write axi_master_write_inst
(
//全局变量
.ACLK (ui_clk ), //全局时钟
.ARESETN (~ui_rst ), //全局复位
.M_AXI_AWID ( M_AXI_AWID ), //写地址ID 用来标志一组写信号
.M_AXI_AWADDR ( M_AXI_AWADDR ), //写地址 给出一次写突发传输的写地址
.M_AXI_AWLEN ( M_AXI_AWLEN ), //突出长度 给出突出传输的次数
.M_AXI_AWSIZE ( M_AXI_AWSIZE ), //突出大小 给出每次突发传输的字节数
.M_AXI_AWBURAST ( M_AXI_AWBURAST ), //突出类型
.M_AXI_AWLOCK ( M_AXI_AWLOCK ), //总线锁信号,可提供操作的原子性
.M_AXI_AWCACHE ( M_AXI_AWCACHE ), //内存类型,表明一次传输是怎么通过系统的
.M_AXI_AWPROT ( M_AXI_AWPROT ), //保护类型,表明一次传输的特权级及安全等级
.M_AXI_AWQOS ( M_AXI_AWQOS ), //质量服务QOS
.M_AXI_AWVALID ( M_AXI_AWVALID ), //有效信号,表明此通道的地址控制信号有效
.M_AXI_AWREADY ( M_AXI_AWREADY ), //表明从机可以接收地址和对应的控制信号
.M_AXI_WDATA (M_AXI_WDATA ), //写数据
.M_AXI_WSTRB (M_AXI_WSTRB ), //写数据有效的字节数
.M_AXI_WLAST (M_AXI_WLAST ), //表明此次传输是最后一个突发传输
.M_AXI_WVALID (M_AXI_WVALID ), //写有效信号,表明此次写有效
.M_AXI_WREADY (M_AXI_WREADY ), //表明从机可以接收写数据
.M_AXI_BID (M_AXI_BID ), //写响应ID TAG
.M_AXI_BRESP (M_AXI_BRESP ), //写响应,表明写传输的状态
.M_AXI_BVALID (M_AXI_BVALID ), //写响应有效
.M_AXI_BREADY (M_AXI_BREADY ), //表明主机能够接收写响应
.WR_START (wr_burst_req ), //写突出触发信号
.WR_ADDR (wr_burst_addr ), //地址
.WR_LEN (wr_burst_len ), //长度
.WR_READY (wr_ready ), //写空闲
.WR_FIFO_RE (wr_fifo_re ), //连接到fifo的读使能
.WR_FIFO_DATA (wr_fifo_data ), //连接到fifo的读数据
.WR_BURAST_FINISH (wr_burst_finish ) //完成最后一次突发
);
axi_master_read axi_master_read_inst
(
//全局变量
.ACLK (ui_clk ), //全局时钟
.ARESETN (~ui_rst ), //全局复位
.M_AXI_ARID (M_AXI_ARID ),
.M_AXI_ARADDR (M_AXI_ARADDR ),
.M_AXI_ARLEN (M_AXI_ARLEN ),
.M_AXI_ARSIZE (M_AXI_ARSIZE ),
.M_AXI_ARBURAST (M_AXI_ARBURAST ),
.M_AXI_ARLOCK (M_AXI_ARLOCK ),
.M_AXI_ARCACHE (M_AXI_ARCACHE ),
.M_AXI_ARPROT (M_AXI_ARPROT ),
.M_AXI_ARQOS (M_AXI_ARQOS ),
.M_AXI_ARVALID (M_AXI_ARVALID ),
.M_AXI_ARREADY (M_AXI_ARREADY ),
.M_AXI_RID (M_AXI_RID ),
.M_AXI_RDATA (M_AXI_RDATA ),
.M_AXI_RSTRB (M_AXI_RSTRB ),
.M_AXI_RLAST (M_AXI_RLAST ),
.M_AXI_RVALID (M_AXI_RVALID ),
.M_AXI_RREADY (M_AXI_RREADY ),
.RD_START (rd_burst_req ),
.RD_ADDR (rd_burst_addr ),
.RD_LEN (rd_burst_len ),
.RD_READY (rd_ready ),
.RD_FIFO_RE (rd_fifo_wr ),
.RD_FIFO_DATA (rd_fifo_data ),
.RD_BURAST_FINISH (rd_burst_finish )
);
axi_ddr3 axi_ddr3_inst
(
// Memory interface ports
.ddr3_addr (ddr3_addr ), // output [14:0]
.ddr3_ba (ddr3_ba ), // output [2:0]
.ddr3_cas_n (ddr3_cas_n ), // output
.ddr3_ck_n (ddr3_ck_n ), // output [0:0]
.ddr3_ck_p (ddr3_ck_p ), // output [0:0]
.ddr3_cke (ddr3_cke ), // output [0:0]
.ddr3_ras_n (ddr3_ras_n ), // output
.ddr3_reset_n (ddr3_reset_n ), // output
.ddr3_we_n (ddr3_we_n ), // output
.ddr3_dq (ddr3_dq ), // inout [31:0]
.ddr3_dqs_n (ddr3_dqs_n ), // inout [3:0]
.ddr3_dqs_p (ddr3_dqs_p ), // inout [3:0]
.init_calib_complete (init_calib_complete), // output
.ddr3_cs_n (ddr3_cs_n ), // output [0:0]
.ddr3_dm (ddr3_dm ), // output [3:0]
.ddr3_odt (ddr3_odt ), // output [0:0]
// Application interface ports
.ui_clk (ui_clk ), // output
.ui_clk_sync_rst (ui_rst ), // output
.mmcm_locked (), // output
.aresetn (reset_n ), // input
.app_sr_req (1'd0 ), // input
.app_ref_req (1'd0 ), // input
.app_zq_req (1'd0 ), // input
.app_sr_active (), // output
.app_ref_ack (), // output
.app_zq_ack (), // output
// Slave Interface Write Address Ports
.s_axi_awid ( M_AXI_AWID ), // input [3:0]
.s_axi_awaddr ( M_AXI_AWADDR ), // input [29:0]
.s_axi_awlen ( M_AXI_AWLEN ), // input [7:0]
.s_axi_awsize ( M_AXI_AWSIZE ), // input [2:0]
.s_axi_awburst ( M_AXI_AWBURAST ), // input [1:0]
.s_axi_awlock ( M_AXI_AWLOCK ), // input [0:0]
.s_axi_awcache ( M_AXI_AWCACHE ), // input [3:0]
.s_axi_awprot ( M_AXI_AWPROT ), // input [2:0]
.s_axi_awqos ( M_AXI_AWQOS ), // input [3:0]
.s_axi_awvalid ( M_AXI_AWVALID ), // input
.s_axi_awready ( M_AXI_AWREADY ), // output
// Slave Interface Write Data Ports
.s_axi_wdata (M_AXI_WDATA ), // input [63:0]
.s_axi_wstrb (M_AXI_WSTRB ), // input [7:0]
.s_axi_wlast (M_AXI_WLAST ), // input
.s_axi_wvalid (M_AXI_WVALID ), // input
.s_axi_wready (M_AXI_WREADY ), // output
// Slave Interface Write Response Ports
.s_axi_bid (M_AXI_BID ), // output [3:0]
.s_axi_bresp (M_AXI_BRESP ), // output [1:0]
.s_axi_bvalid (M_AXI_BVALID ), // output
.s_axi_bready (M_AXI_BREADY ), // input
// Slave Interface Read Address Ports
.s_axi_arid (M_AXI_ARID ), // input [3:0]
.s_axi_araddr (M_AXI_ARADDR ), // input [29:0]
.s_axi_arlen (M_AXI_ARLEN ), // input [7:0]
.s_axi_arsize (M_AXI_ARSIZE ), // input [2:0]
.s_axi_arburst (M_AXI_ARBURAST ), // input [1:0]
.s_axi_arlock (M_AXI_ARLOCK ), // input [0:0]
.s_axi_arcache (M_AXI_ARCACHE ), // input [3:0]
.s_axi_arprot (M_AXI_ARPROT ), // input [2:0]
.s_axi_arqos (M_AXI_ARQOS ), // input [3:0]
.s_axi_arvalid (M_AXI_ARVALID ), // input
.s_axi_arready (M_AXI_ARREADY ), // output
// Slave Interface Read Data Ports
.s_axi_rid (M_AXI_RID ), // output [3:0]
.s_axi_rdata (M_AXI_RDATA ), // output [63:0]
.s_axi_rresp (M_AXI_RSTRB ), // output [1:0]
.s_axi_rlast (M_AXI_RLAST ), // output
.s_axi_rvalid (M_AXI_RVALID ), // output
.s_axi_rready (M_AXI_RREADY ), // input
// System Clock Ports
.sys_clk_i (ddr3_clk ),
// Reference Clock Ports
.clk_ref_i (ddr3_clk ),
.sys_rst (reset_n ) // input sys_rst
);
endmodule
(6)数据生成模块以及顶层文件:
module ddr3_data
(
input wire clk_100M ,
input wire reset_n ,
input wire [15:0] rd_data ,
input wire rd_data_valid ,
output reg [15:0] wr_data ,
output reg wr_en ,
output reg rd_en ,
output reg read_enable
);
always@(posedge clk_100M or negedge reset_n)
if(!reset_n)begin
wr_data <= 16'd0;
wr_en <= 1'd0;
read_enable<= 1'd0;
end
else if(wr_data == 16'd1024)begin
wr_data <= 16'd1024;
wr_en <= 1'd0;
read_enable <= 1'd1;
end
else begin
wr_en <= 1'd1;
wr_data <= wr_data + 16'd1;
read_enable <= 1'd0;
end
always@(posedge clk_100M or negedge reset_n)
if(!reset_n)
rd_en <= 1'd0;
else if(read_enable && rd_data_valid)
rd_en <= 1'd1;
else
rd_en <= 1'd0;
endmodule
module ddr3_test
(
input wire clk ,
input wire reset_n ,
output wire ddr3_ck_n ,
output wire ddr3_ck_p ,
output wire ddr3_cke ,
output wire ddr3_reset_n ,
output wire [14:0] ddr3_addr ,
output wire [2:0] ddr3_ba ,
output wire ddr3_cs_n ,
output wire ddr3_cas_n ,
output wire ddr3_ras_n ,
output wire ddr3_odt ,
output wire ddr3_we_n ,
inout wire [31:0] ddr3_dq ,
inout wire [3:0] ddr3_dqs_n ,
inout wire [3:0] ddr3_dqs_p ,
output wire [3:0] ddr3_dm
);
wire clk_320M ;
wire clk_100M ;
wire locked ;
wire rst_n ;
wire data_rst_n ;
wire init_calib_complete ;
wire ui_clk ;
wire ui_rst ;
(*mark_debug = "true"*)wire [15:0] rd_data ;
(*mark_debug = "true"*)wire rd_data_valid ;
(*mark_debug = "true"*)wire [15:0] wr_data ;
(*mark_debug = "true"*)wire wr_en ;
(*mark_debug = "true"*)wire rd_en ;
(*mark_debug = "true"*)wire read_enable ;
assign rst_n = reset_n & locked;
assign data_rst_n = rst_n & init_calib_complete & (!ui_rst);
clk_gen clk_gen_inst
(
.clk_320M (clk_320M ),
.clk_100M (clk_100M ),
.reset (~reset_n ),
.locked (locked ),
.clk_in1 (clk )
);
axi_ddr3_top axi_ddr3_top_inst
(
.ddr3_clk (clk_320M ),
.reset_n (rst_n ),
.pingpang (1'd0 ),
.ui_clk (ui_clk ),
.ui_rst (ui_rst ),
.init_calib_complete (init_calib_complete ),
.wr_b_addr (32'd0 ),
.wr_e_addr (32'd2048 ),
.wr_clk (clk_100M ),
.data_wren (wr_en ),
.data_wr (wr_data ),
.wr_rst (1'd0 ),
.rd_b_addr (32'd0 ),
.rd_e_addr (32'd2048 ),
.rd_clk (clk_100M ),
.data_rden (rd_en ),
.data_rd (rd_data ),
.rd_rst (1'd0 ),
.read_enable (read_enable ),
.rd_data_valid (rd_data_valid ),
.ddr3_ck_n (ddr3_ck_n ),
.ddr3_ck_p (ddr3_ck_p ),
.ddr3_cke (ddr3_cke ),
.ddr3_reset_n (ddr3_reset_n ),
.ddr3_addr (ddr3_addr ),
.ddr3_ba (ddr3_ba ),
.ddr3_cs_n (ddr3_cs_n ),
.ddr3_cas_n (ddr3_cas_n ),
.ddr3_ras_n (ddr3_ras_n ),
.ddr3_odt (ddr3_odt ),
.ddr3_we_n (ddr3_we_n ),
.ddr3_dq (ddr3_dq ),
.ddr3_dqs_n (ddr3_dqs_n ),
.ddr3_dqs_p (ddr3_dqs_p ),
.ddr3_dm (ddr3_dm )
);
ddr3_data ddr3_data_inst
(
.clk_100M (clk_100M ),
.reset_n (data_rst_n ),
.rd_data (rd_data ),
.rd_data_valid (rd_data_valid ),
.wr_data (wr_data ),
.wr_en (wr_en ),
.rd_en (rd_en ),
.read_enable (read_enable )
);
endmodule
()仿真模型位置及仿真波形分析
- 仿真文件模型位置:
- 时钟生成模块仿真波形:
- 数据生成模块仿真波形:
(7)配置ILA以及实验现象