65.DDR3读写控制器的设计与验证(2)
(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 , //质量服务QOSoutput 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 TAGinput 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)beginWR_STATE <= S0_WR_IDLE;awaddr_reg <= 32'd0;awlen_reg <= 8'd0;awvalid_reg <= 1'd0;wvalid_reg <= 1'd0;endelse begincase(WR_STATE)S0_WR_IDLE :beginawlen_reg <= 8'd0;awvalid_reg <= 1'd0;wvalid_reg <= 1'd0;if(WR_START == 1'd1)beginWR_STATE <= S1_WR_WAIT;awaddr_reg <= WR_ADDR;endend S1_WR_WAIT :beginWR_STATE <= S2_WR_ADDR;end S2_WR_ADDR :beginWR_STATE <= S3_WD_WAIT;awvalid_reg <= 1'd1;wvalid_reg <= 1'd1;end S3_WD_WAIT :beginif(M_AXI_AWREADY == 1'd1)beginWR_STATE <= S4_WD_PROC;awvalid_reg <= 1'd0;awlen_reg <= WR_LEN - 8'd1;endend S4_WD_PROC :beginif(M_AXI_WREADY == 1'd1)beginif(M_AXI_WLAST == 1'd1)beginWR_STATE <= S5_WR_RES;wvalid_reg <= 1'd0;end else beginawlen_reg <= awlen_reg - 8'd1;WR_STATE <= WR_STATE;endendend S5_WR_RES :beginif(M_AXI_BVALID)beginWR_STATE <= S6_WR_DONE;endend S6_WR_DONE :beginWR_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)beginRD_STATE <= S0_RA_IDLE;araddr_reg <= 32'd0;arvalid_reg <= 1'd0;endelse begincase(RD_STATE)S0_RA_IDLE :beginarvalid_reg <= 1'd0;if(RD_START == 1'd1)beginRD_STATE <= S1_RA_WAIT;araddr_reg <= RD_ADDR;endend S1_RA_WAIT :beginRD_STATE <= S2_RA_ADDR;end S2_RA_ADDR :beginRD_STATE <= S3_RD_WAIT;arvalid_reg <= 1'd1;end S3_RD_WAIT :beginif(M_AXI_ARREADY == 1'd1)beginRD_STATE <= S4_RD_PROC;arvalid_reg <= 1'd0; endend S4_RD_PROC :beginif(M_AXI_RREADY == 1'd1)beginif(M_AXI_RLAST == 1'd1)beginRD_STATE <= S5_RD_DONE;end endend S5_RD_DONE :beginRD_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 ,//写FIFOinput 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 ,//读FIFOinput 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)beginwr_burst_addr_reg <= wr_b_addr;pingpang_reg <= 1'd0;endelse if(wr_burst_finish)beginwr_burst_addr_reg <= wr_burst_addr_reg + (MAX_DDR_WR_LEN << 3);if(pingpang == 1'd1)beginif(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;endelse beginif(wr_burst_addr_reg >= wr_e_addr - (MAX_DDR_WR_LEN << 3))wr_burst_addr_reg <= wr_b_addr;endendelse 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)beginif(pingpang == 1'd1)beginrd_burst_addr_reg <= rd_e_addr;endelse beginrd_burst_addr_reg <= rd_b_addr;end endelse if(rd_burst_finish)beginrd_burst_addr_reg <= rd_burst_addr_reg + (MAX_DDR_RD_LEN << 3);if(pingpang == 1'd1)beginif((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))))beginif(pingpang_reg)rd_burst_addr_reg <= rd_b_addr;else rd_burst_addr_reg <= rd_e_addr;endendelse beginif(rd_burst_addr_reg >= rd_e_addr - (MAX_DDR_RD_LEN << 3))rd_burst_addr_reg <= rd_b_addr;endendelse 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 ,//写FIFOinput 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)beginwr_data <= 16'd0;wr_en <= 1'd0;read_enable<= 1'd0;endelse if(wr_data == 16'd1024)beginwr_data <= 16'd1024;wr_en <= 1'd0;read_enable <= 1'd1;endelse beginwr_en <= 1'd1;wr_data <= wr_data + 16'd1;read_enable <= 1'd0;endalways@(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以及实验现象