1. 工程代码下载:
2. 利用Mark_debug 抓取的波形如下:

图1 写波形

图2 读波形
3. 测试源程序
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2020/05/12 17:45:17
// Design Name:
// Module Name: ddr_rd_wrrd_wr
// Project Name: ddr3_intf
// Target Devices: Artix 7 100T
// Tool Versions:
// Description:
//
// Dependencies:
// clock ratio 4:1
// DDR clock frequency 400Mhz
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ddr_rd_wr(
// input [127:0] data_in,
(* MARK_DEBUG="true" *) output reg [26:0] app_addr ,
(* MARK_DEBUG="true" *) output reg [2:0] app_cmd ,
(* MARK_DEBUG="true" *) output reg app_en ,
(* MARK_DEBUG="true" *) input app_rdy ,
(* MARK_DEBUG="true" *) output reg [127:0] app_wdf_data ,
output reg [15:0] app_wdf_mask ,
(* MARK_DEBUG="true" *) output app_wdf_end ,
(* MARK_DEBUG="true" *) output reg app_wdf_wren ,
(* MARK_DEBUG="true" *) input app_wdf_rdy ,
(* MARK_DEBUG="true" *) input [127:0] app_rd_data ,
(* MARK_DEBUG="true" *) input app_rd_data_end ,
(* MARK_DEBUG="true" *) input app_rd_data_valid ,
input clk ,
input rst_n ,
(* MARK_DEBUG="true" *) output reg error_flag = 0 ,
output reg end_flag = 0
);
parameter BURST_WR_128BIT = 16777216 ; //0x100_0000 测试写容量
parameter BURST_RD_128BIT = 16777216 ; //0x100_0000 测试读容量
parameter DATA = 128'habcdef1234567890abcdef1234567890 ; //测试数据
// Read and write once every 1 second
(* MARK_DEBUG="true" *) reg [27:0] scnt = 0 ; // 分频 ,将100M时钟分频成 周期2秒的方波,高电平和低电平各1秒。
always @ (posedge clk)
if (!rst_n)
begin
scnt <= 0 ;
end_flag <= 0 ;
end
else if (scnt < 28'd199_999_999)
begin
scnt <= scnt + 1;
end_flag <= 0 ;
end
else
begin
scnt <= 0 ;
end_flag <= ~end_flag ;
end
(* MARK_DEBUG="true" *) wire time_wrreq = ( scnt == 28'd100_000_000 ) ;
(* MARK_DEBUG="true" *) wire time_rdreq = ( scnt == 28'd000_000_000) ;
(* MARK_DEBUG="true" *) reg[1:0] cstate; //current state
reg[1:0] nstate; //next state
(* MARK_DEBUG="true" *) reg [31:0] num = 0 ;
(* MARK_DEBUG="true" *) reg [31:0] wrnum = 0 ;
always @ (posedge clk )
if (!rst_n)
cstate <= 0 ;
else cstate <=nstate ;
always @(cstate , time_wrreq ,time_rdreq ,num ,app_rdy ,app_wdf_rdy)
case (cstate)
0 : begin
if ( time_wrreq ) //write request
nstate <= 1 ;
else if (time_rdreq )
nstate <= 2 ;
else nstate <= 0 ;
end
1: begin
if (( wrnum >= BURST_WR_128BIT) && (num >=BURST_WR_128BIT ) )
nstate <= 3 ;
else
nstate <= 1 ;
end
2: begin
if (num >= BURST_RD_128BIT)
nstate <= 3 ;
else
nstate <= 2 ;
end
3: begin
nstate <= 0 ;
end
endcase
always @ (posedge clk)
if (!rst_n)
num <= 32'd0 ;
else
if (cstate ==1)
begin
if ( app_rdy & app_en )
num <= num+ 1 ;
end
else
if ( cstate == 2)
begin
if (app_rdy & app_en)
num <= num +1 ;
end
else num <= 0 ;
always @ ( posedge clk)
if (!rst_n) wrnum <= 32'd0 ;
else
if (cstate == 1)
begin
if (app_wdf_rdy & app_wdf_wren) begin
wrnum <= wrnum +1 ;
end
end
else wrnum <= 0 ;
////////////////////////////////////////////////////
//地址命令
//reg[27:0] app_addr, //DDR3地址总线
//reg[2:0] app_cmd, //DDR3命令总线: 3‘b000--写;3'b001--读;
//reg app_en, //地址命令使能,高电平有效
// 读写数据
always@ (posedge clk )
if (~rst_n)
begin
app_cmd <= 3'd0 ;
app_en <= 1'b0 ;
app_addr <=27'd0 ;
end
else begin
if ( cstate == 1)
begin
app_cmd <= 3'b000 ; //write data to ddr3
if ( num < BURST_WR_128BIT )
app_en <= 1 ;
else
app_en <= 0 ;
if (app_rdy & app_en)
app_addr[26:3] <= app_addr[26:3]+1 ; // app_addr[10:3] +1'b1 ; 8 data ,16bits
end
else begin
if (cstate == 2)
begin
if (num <BURST_RD_128BIT)
app_en <= 1'b1 ;
else
app_en <= 1'b0 ;
if (app_rdy&app_en) begin
app_cmd <= 3'b001 ;
app_addr[26:3] <= app_addr[26:3] + 1 ;
end
end
else
begin
app_cmd <= 3'd0 ;
app_en <= 1'b0 ;
app_addr <= 27'd0 ;
end
end
end
//
always @ ( posedge clk)
if (!rst_n)
begin
app_wdf_data <= 128'd0 ;
app_wdf_mask<=16'd0;
app_wdf_wren <= 0 ;
end
else
begin
app_wdf_mask<=16'd0;
if(cstate == 1)
begin
app_wdf_data <= DATA ;//prepare the data
if (wrnum <= BURST_WR_128BIT )
app_wdf_wren <= 1'b1 ;
else
app_wdf_wren <= 1'b0 ;
if (app_wdf_rdy & app_wdf_wren)
app_wdf_data <= DATA ;
end
else
begin
app_wdf_data <= 128'd0 ;
app_wdf_wren <= 0 ;
end
end
assign app_wdf_end = 1'b1;
always @(posedge clk or negedge rst_n)
if(!rst_n) begin
error_flag <= 0;
end
else begin
if(app_rd_data_valid&&(app_rd_data!= DATA))
error_flag <= 1 ;
else error_flag <=0 ;
end
endmodule
老师好,在学习时遇到一个问题,请老师解答:
1、本文中定义常量BURST_RD_128BIT=16777216,请问老师这里的数值(16777216)代表什么含义,是如何计算得到的呢?请老师详细讲解一下,谢谢老师!
FII-PRX100-D硬件上所使用的DDR芯片型号为MT41J128M16HA-125,容量为256M bytes。BURST_RD_128BIT = 16777216 表示 2 ^24(16777216) * 128bit = 2 ^24 * 128/ 8 bytes = 256M bytes。可以实现对全片进行测试。
老师,请教一下,我们ddr3控制器的地址映射选择的是ROW+BANK+COLUMN, 上面测试程序里面的app_addr[26:3] +1 如果第一行的列地址加完,再加一不是直接加在了bank上面么,按道理应该是这一行的列写完,就应该下一行的第一列开始。地址映射应该是BANK+ROW+COLUMN 才对?
app_wdf_rdy写成了输入 是否有误
老师 wr_num 和num是什么区别?