该项目的描述是,FPGA向DDR3芯片写入数据,然后再读出数据,从而验证读写模块的正确性。该项目具有一定的实际意义,就是我们新制作的一块FPGA板卡,最有可能出问题的部分就是DDR芯片,因为DDR的实际属于高速设计,然后我们将对应的循环测试的程序下载进去,验证我们硬件板卡的正确性。通过本项目,我们可以学到VIVADO MIG的读写DDR3的方法,便可以掌握VIVADO 操作DDR3的操作流程。
本次实验所用到的软件环境:
1、VIVADO2019.1软件开发环境
2、modelsim仿真环境
3、米联客MA7035FA
对于生成的MIG IP核,我们现在对其接口信号做出相应的描述,以便于大家可以充分理解信号的作用,
mig_7series_0 mig_7series_0_inst (
// Memory interface ports
.ddr3_addr (ddr3_addr ), // output [13:0] ddr3_addr
.ddr3_ba (ddr3_ba ), // output [2:0] ddr3_ba
.ddr3_cas_n (ddr3_cas_n ), // output ddr3_cas_n
.ddr3_ck_n (ddr3_ck_n ), // output [0:0] ddr3_ck_n
.ddr3_ck_p (ddr3_ck_p ), // output [0:0] ddr3_ck_p
.ddr3_cke (ddr3_cke ), // output [0:0] ddr3_cke
.ddr3_ras_n (ddr3_ras_n ), // output ddr3_ras_n
.ddr3_reset_n (ddr3_reset_n ), // output ddr3_reset_n
.ddr3_we_n (ddr3_we_n ), // output ddr3_we_n
.ddr3_dq (ddr3_dq ), // inout [31:0] ddr3_dq
.ddr3_dqs_n (ddr3_dqs_n ), // inout [3:0] ddr3_dqs_n
.ddr3_dqs_p (ddr3_dqs_p ), // inout [3:0] ddr3_dqs_p
.init_calib_complete (init_calib_complete ), // output init_calib_complete
.ddr3_cs_n (ddr3_cs_n ), // output [0:0] ddr3_cs_n
.ddr3_dm (ddr3_dm ), // output [3:0] ddr3_dm
.ddr3_odt (ddr3_odt ), // output [0:0] ddr3_odt
// Application interface ports
.app_addr ( ), // input [27:0] app_addr
.app_cmd ( ), // input [2:0] app_cmd
.app_en ( ), // input app_en
.app_wdf_data ( ), // input [255:0] app_wdf_data
.app_wdf_end ( ), // input app_wdf_end
.app_wdf_wren ( ), // input app_wdf_wren
.app_rd_data ( ), // output [255:0] app_rd_data
.app_rd_data_end ( ), // output app_rd_data_end
.app_rd_data_valid ( ), // output app_rd_data_valid
.app_rdy ( ), // output app_rdy
.app_wdf_rdy ( ), // output app_wdf_rdy
.app_sr_req (1'b0 ), // input app_sr_req
.app_ref_req (1'b0 ), // input app_ref_req
.app_zq_req (1'b0 ), // input app_zq_req
.app_sr_active ( ), // output app_sr_active
.app_ref_ack ( ), // output app_ref_ack
.app_zq_ack ( ), // output app_zq_ack
.ui_clk (ui_clk ), // output ui_clk
.ui_clk_sync_rst (ui_clk_sync_rst ), // output ui_clk_sync_rst
.app_wdf_mask (app_wdf_mask ), // input [31:0] app_wdf_mask
// System Clock Ports
.sys_clk_i (clk_200m ),
.sys_rst (locked ) // input sys_rst
);
查阅技术手册,我们对上面的信号做系列陈述:
1、所有前缀是ddr3的信号,都是与DDR硬件连接的信号,具体含义参考DDR的数据手册,相信如果大家学过SDRAM控制器,对下面的信号很熟悉:
ddr3_addr
ddr3_ba
ddr3_cas_n
ddr3_ck_n
ddr3_ck_p
ddr3_cke
ddr3_ras_n
ddr3_reset_n
ddr3_we_n
ddr3_dq
ddr3_dqs_n
ddr3_dqs_p
init_calib_complete
ddr3_cs_n
ddr3_dm
ddr3_odt
2、init_calib_complete信号,MIG IP核的初始化信号,MIG自我配置成功之后,该信号拉高,对DDR的操作必须等到该位拉高之后进行
3、app_addr信号,提供给我们的地址信号,注意这里与ISE中的不太一样,ISE中的是字节地址,而vivado对应DDR3的实际地址
4、app_cmd信号,用户给DDR芯片的读写命令信号,0是写命令,1是读命令
5、app_en信号,命令路径的使能信号,该信号有效时,app_cmd、app_addr信号才有效,其余的时刻信号无效
6、app_wdf_data信号、数据路径的数据信号
7、app_wdf_end信号,数据一次突发结束信号,4:1模式下与app_wdf_wren相同,2:1模式下app_wdf_wren每两个app_wdf_end使能一次
8、app_wdf_wren信号,写路径数据的有效信号
9、app_wdf_rdy信号,MIG信号给用户的信号,在该信号与app_wdf_wren信号同时有效时,数据被写入DDR芯片
10、app_rd_data信号,DDR3芯片给用户的数据信号
11、app_rd_data_end信号,DDR3给用户读命令结束信号
12、app_rd_data_valid信号,DDR3芯片给用户数据有效信号
13、app_rdy信号,命令路径准备好接受用户的命令信号,与app_en有效时命令有效
14、app_sr_req 、app_ref_req、app_zq_req信号,一系列的请求信号,一般为0代表用户对MIG IP没有强力干预
15、app_sr_active、app_ref_ack、app_zq_ack信号,上面请求的响应信号
16、ui_clk信号,MIG给用户使用的时钟,用户对MIG IP核的操作必须使用该时钟
17、ui_clk_sync_rst信号,MIG给用户使用的复位信号,用户对MIG IP核的操作必须使用该复位信号
18、app_wdf_mask信号,写数据的掩码
19、sys_clk_i信号,MIG的系统时钟,在MIG的选项中选择了200MHz
20、sys_rst信号,MIG IP核的复位信号,与系统时钟相关联
我们从技术手册中查找写时序的图形如下:
当用户逻辑 app_en 信号有效并且 app_rdy 信号有效时,命令被 接受并写入 FIFO。
当 app_rdy 被取消置位时,用户逻辑需要将 app_en 保持为高电平以及有效的命
令和地址值,直到 app_rdy 有效。
此图描述了 app_wdf_data , app_wdf_wren 和 app_wdf_end 信号的三种场景,
如下所示:
1.写入数据以及相应的写入命令( BL8 的下半部分)。
2.写入数据在相应的写入命令之前。
3.写入数据在相应的写命令之后,不应超过两个时钟周期的限制。
对于在写入命令后输出的写入数据,如注 3 所示,最大延迟为两个时钟周期。
上面的模式时no-back-back模式,当是back-back模式的情况下,没有最大延迟的限制
上面便是back-back模式,通俗来讲就是命令是连续的。
读时序如上图,读取的数据由 MIG以请求的顺序返回,并且在 app_rd_data_valid 有效时数据有效。app_rd_data_end 信号表示每个读命令脉冲串的结束,在用户逻辑中不需要。
读写设计的时序如下图,以下两张图是一个模块的时序设计图,为了观看方便我们截了两张图片:
有了上面的时序图,我们可以比较方便的设计出响应的逻辑代码。
ddr3_top模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : ddr3_top.v
// Create Time : 2020-02-27 23:16:16
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module ddr3_top(
//System Interfaces
input sclk ,
input rst_n ,
//DDR3 Interfaces
output wire [13:0] ddr3_addr ,
output wire [ 2:0] ddr3_ba ,
output wire ddr3_cas_n ,
output wire ddr3_ck_n ,
output wire ddr3_ck_p ,
output wire ddr3_cke ,
output wire ddr3_ras_n ,
output wire ddr3_reset_n ,
output wire ddr3_we_n ,
inout [31:0] ddr3_dq ,
inout [ 3:0] ddr3_dqs_n ,
inout [ 3:0] ddr3_dqs_p ,
output wire [ 0:0] ddr3_cs_n ,
output wire [ 3:0] ddr3_dm ,
output wire [ 0:0] ddr3_odt
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
wire locked ;
wire clk_200m ;
//mig_7series_0_inst
wire init_calib_complete ;
wire [27:0] app_addr ;
wire [ 2:0] app_cmd ;
wire app_en ;
wire [255:0] app_wdf_data ;
wire app_wdf_end ;
wire app_wdf_wren ;
wire [255:0] app_rd_data ;
wire app_rd_data_end ;
wire app_rd_data_valid ;
wire app_rdy ;
wire app_wdf_rdy ;
wire [31:0] app_wdf_mask ;
wire ui_clk ;
wire ui_clk_sync_rst ;
//Debug
wire test_start ;
wire test_busy ;
wire [63:0] error_num ;
wire error_done ;
wire test ;
reg test_r ;
reg test_r2 ;
reg test_r3 ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
clk_wiz_0 clk_wiz_0_inst(
// Clock out ports
.clk_out1 (clk_200m ), // output clk_out1
// Status and control signals
.reset (~rst_n ), // input reset
.locked (locked ), // output locked
// Clock in ports
.clk_in1 (sclk )
); // input clk_in1
mig_7series_0 mig_7series_0_inst (
// Memory interface ports
.ddr3_addr (ddr3_addr ), // output [13:0] ddr3_addr
.ddr3_ba (ddr3_ba ), // output [2:0] ddr3_ba
.ddr3_cas_n (ddr3_cas_n ), // output ddr3_cas_n
.ddr3_ck_n (ddr3_ck_n ), // output [0:0] ddr3_ck_n
.ddr3_ck_p (ddr3_ck_p ), // output [0:0] ddr3_ck_p
.ddr3_cke (ddr3_cke ), // output [0:0] ddr3_cke
.ddr3_ras_n (ddr3_ras_n ), // output ddr3_ras_n
.ddr3_reset_n (ddr3_reset_n ), // output ddr3_reset_n
.ddr3_we_n (ddr3_we_n ), // output ddr3_we_n
.ddr3_dq (ddr3_dq ), // inout [31:0] ddr3_dq
.ddr3_dqs_n (ddr3_dqs_n ), // inout [3:0] ddr3_dqs_n
.ddr3_dqs_p (ddr3_dqs_p ), // inout [3:0] ddr3_dqs_p
.init_calib_complete (init_calib_complete ), // output init_calib_complete
.ddr3_cs_n (ddr3_cs_n ), // output [0:0] ddr3_cs_n
.ddr3_dm (ddr3_dm ), // output [3:0] ddr3_dm
.ddr3_odt (ddr3_odt ), // output [0:0] ddr3_odt
// Application interface ports
.app_addr (app_addr ), // input [27:0] app_addr
.app_cmd (app_cmd ), // input [2:0] app_cmd
.app_en (app_en ), // input app_en
.app_wdf_data (app_wdf_data ), // input [255:0] app_wdf_data
.app_wdf_end (app_wdf_end ), // input app_wdf_end
.app_wdf_wren (app_wdf_wren ), // input app_wdf_wren
.app_rd_data (app_rd_data ), // output [255:0] app_rd_data
.app_rd_data_end (app_rd_data_end ), // output app_rd_data_end
.app_rd_data_valid (app_rd_data_valid ), // output app_rd_data_valid
.app_rdy (app_rdy ), // output app_rdy
.app_wdf_rdy (app_wdf_rdy ), // output app_wdf_rdy
.app_sr_req (1'b0 ), // input app_sr_req
.app_ref_req (1'b0 ), // input app_ref_req
.app_zq_req (1'b0 ), // input app_zq_req
.app_sr_active ( ), // output app_sr_active
.app_ref_ack ( ), // output app_ref_ack
.app_zq_ack ( ), // output app_zq_ack
.ui_clk (ui_clk ), // output ui_clk
.ui_clk_sync_rst (ui_clk_sync_rst ), // output ui_clk_sync_rst
.app_wdf_mask (app_wdf_mask ), // input [31:0] app_wdf_mask
// System Clock Ports
.sys_clk_i (clk_200m ),
.sys_rst (locked ) // input sys_rst
);
ddr3_drive ddr3_drive_inst(
//DDR3 Interfaces
.ui_clk (ui_clk ),
.ui_clk_sync_rst ((~ui_clk_sync_rst) && init_calib_complete),
.app_addr (app_addr ),
.app_cmd (app_cmd ),
.app_en (app_en ),
.app_rdy (app_rdy ),
.app_wdf_data (app_wdf_data ),
.app_wdf_mask (app_wdf_mask ),
.app_wdf_rdy (app_wdf_rdy ),
.app_wdf_wren (app_wdf_wren ),
.app_wdf_end (app_wdf_end ),
.app_rd_data (app_rd_data ),
.app_rd_data_valid (app_rd_data_valid ),
//Debug
.test_start (test_start ),
.test_busy (test_busy ),
.error_num (error_num ),
.error_done (error_done )
);
//========================================================================================\
//******************************* Debug **********************************
//========================================================================================/
always @(posedge sclk)begin
test_r <= test;
test_r2 <= test_r;
test_r3 <= test_r2;
end
assign test_start = ~test_r3 && test_r2;
vio_0 vio_0_inst (
.clk (ui_clk ), // input wire clk
.probe_out0 (test ) // output wire [0 : 0] probe_out0
);
ila_0 ila_0_inst (
.clk (ui_clk ), // input wire clk
.probe0 (app_addr ), // input wire [27:0] probe0
.probe1 (app_cmd ), // input wire [2:0] probe1
.probe2 (app_en ), // input wire [0:0] probe2
.probe3 (app_rdy ), // input wire [0:0] probe3
.probe4 (app_wdf_data ), // input wire [255:0] probe4
.probe5 (app_wdf_mask ), // input wire [31:0] probe5
.probe6 (app_wdf_rdy ), // input wire [0:0] probe6
.probe7 (app_wdf_wren ), // input wire [0:0] probe7
.probe8 (app_wdf_end ), // input wire [0:0] probe8
.probe9 (app_rd_data ), // input wire [255:0] probe9
.probe10 (app_rd_data_valid ), // input wire [0:0] probe10
.probe11 (test_start ), // input wire [0:0] probe11
.probe12 (test_busy ), // input wire [0:0] probe12
.probe13 (error_num ), // input wire [63:0] probe13
.probe14 (error_done ) // input wire [0:0] probe14
);
endmodule
ddr3_drive模块
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : ddr3_drive.v
// Create Time : 2020-02-28 22:10:02
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module ddr3_drive(
//DDR3 Interfaces
input ui_clk ,
input ui_clk_sync_rst ,
output wire [27:0] app_addr ,
output reg [ 2:0] app_cmd ,
output reg app_en ,
input app_rdy ,
output reg [255:0] app_wdf_data ,
output wire [31:0] app_wdf_mask ,
input app_wdf_rdy ,
output reg app_wdf_wren ,
output wire app_wdf_end ,
input [255:0] app_rd_data ,
input app_rd_data_valid ,
//Debug
input test_start ,
output reg test_busy ,
output reg [63:0] error_num ,
output reg error_done
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter BL_NUM_END = 1048576 ;
//parameter BL_NUM_END = 100 ;
parameter BL_LENGTH = 16 ;
parameter CMD_WR = 3'b000 ;
parameter CMD_RD = 3'b001 ;
reg [20:0] bl_cnt ;
reg [ 6:0] cmd_cnt ;
reg [27:0] wr_addr ;
reg app_en_r ;
reg [ 6:0] wr_cnt ;
reg [ 6:0] rd_cnt ;
reg [27:0] rd_addr ;
reg [255:0] check_data ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign app_wdf_mask = 32'd0;
assign app_wdf_end = app_wdf_wren;
assign app_addr = app_cmd == CMD_RD ? rd_addr : wr_addr;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
test_busy <= 1'b0;
else if(test_start == 1'b1)
test_busy <= 1'b1;
else if(bl_cnt == (BL_NUM_END-1'b1) && rd_cnt == BL_LENGTH)
test_busy <= 1'b0;
else
test_busy <= test_busy;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
app_en <= 1'b0;
else if(test_busy == 1'b0 && test_start == 1'b1)
app_en <= 1'b1;
else if(cmd_cnt == BL_LENGTH && wr_cnt == BL_LENGTH)
app_en <= 1'b1;
else if(bl_cnt < (BL_NUM_END-1'b1) && rd_cnt == BL_LENGTH)
app_en <= 1'b1;
else if(cmd_cnt == (BL_LENGTH-1) && app_rdy == 1'b1)
app_en <= 1'b0;
else
app_en <= app_en;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
app_cmd <= CMD_WR;
else if(test_busy == 1'b0 && test_start == 1'b1)
app_cmd <= CMD_WR;
else if(cmd_cnt == BL_LENGTH && wr_cnt == BL_LENGTH)
app_cmd <= CMD_RD;
else if(rd_cnt == BL_LENGTH)
app_cmd <= CMD_WR;
else
app_cmd <= app_cmd;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
cmd_cnt <= 7'd0;
else if(cmd_cnt == BL_LENGTH && wr_cnt == BL_LENGTH)
cmd_cnt <= 7'd0;
else if(cmd_cnt == BL_LENGTH && rd_cnt == BL_LENGTH)
cmd_cnt <= 7'd0;
else if(app_en == 1'b1 && app_rdy == 1'b1)
cmd_cnt <= cmd_cnt + 1'b1;
else
cmd_cnt <= cmd_cnt;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
wr_addr <= 28'd0;
else if(test_start == 1'b1 && test_busy == 1'b0)
wr_addr <= 28'd0;
else if(app_en == 1'b1 && app_rdy == 1'b1 && app_cmd == CMD_WR)
wr_addr <= wr_addr + 8;
else
wr_addr <= wr_addr;
always @(posedge ui_clk)
app_en_r <= app_en;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
app_wdf_wren <= 1'b0;
else if(wr_cnt == BL_LENGTH-1 && app_wdf_rdy == 1'b1)
app_wdf_wren <= 1'b0;
else if(app_cmd == CMD_WR && app_en_r == 1'b1 && wr_cnt < BL_LENGTH)
app_wdf_wren <= 1'b1;
else
app_wdf_wren <= app_wdf_wren;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
app_wdf_data <= 256'd0;
else if(app_wdf_wren == 1'b1 && app_wdf_rdy == 1'b1)
app_wdf_data <= app_wdf_data + 1'b1;
else
app_wdf_data <= app_wdf_data;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
wr_cnt <= 7'd0;
else if(wr_cnt == BL_LENGTH && cmd_cnt == BL_LENGTH)
wr_cnt <= 7'd0;
else if(app_wdf_wren == 1'b1 && app_wdf_rdy == 1'b1)
wr_cnt <= wr_cnt + 1'b1;
else
wr_cnt <= wr_cnt;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
rd_cnt <= 7'd0;
else if(rd_cnt == BL_LENGTH)
rd_cnt <= 7'd0;
else if(app_rd_data_valid == 1'b1)
rd_cnt <= rd_cnt + 1'b1;
else
rd_cnt <= rd_cnt;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
rd_addr <= 28'd0;
else if(test_start == 1'b1 && test_busy == 1'b0)
rd_addr <= 28'd0;
else if(app_en == 1'b1 && app_rdy == 1'b1 && app_cmd == CMD_RD)
rd_addr <= rd_addr + 8;
else
rd_addr <= rd_addr;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
bl_cnt <= 21'd0;
else if(bl_cnt == BL_NUM_END-1 && rd_cnt == BL_LENGTH)
bl_cnt <= 21'd0;
else if(rd_cnt == BL_LENGTH)
bl_cnt <= bl_cnt + 1'b1;
else
bl_cnt <= bl_cnt;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
check_data <= 256'd0;
else if(app_rd_data_valid == 1'b1)
check_data <= check_data + 1'b1;
else
check_data <= check_data;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
error_num <= 64'd0;
else if(test_start == 1'b1)
error_num <= 64'd0;
else if(app_rd_data_valid == 1'b1 && check_data != app_rd_data)
error_num <= error_num + 1'b1;
else
error_num <= error_num;
always @(posedge ui_clk or negedge ui_clk_sync_rst)
if(ui_clk_sync_rst == 1'b0)
error_done <= 1'b0;
else if(bl_cnt == BL_NUM_END-1 && rd_cnt == BL_LENGTH)
error_done <= 1'b1;
else
error_done <= 1'b0;
endmodule
tb_ddr3模块:
`timescale 1ns / 1ps
`define CLOCK 20
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : tb_ddr3.v
// Create Time : 2020-02-27 23:36:46
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module tb_ddr3;
parameter DQ_WIDTH = 32;
localparam MEMORY_WIDTH = 16;
localparam NUM_COMP = DQ_WIDTH/MEMORY_WIDTH ;
reg sclk ;
reg rst_n ;
wire [13:0] ddr3_addr ;
wire [ 2:0] ddr3_ba ;
wire ddr3_cas_n ;
wire ddr3_ck_n ;
wire ddr3_ck_p ;
wire ddr3_cke ;
wire ddr3_ras_n ;
wire ddr3_reset_n ;
wire ddr3_we_n ;
wire [31:0] ddr3_dq ;
wire [ 3:0] ddr3_dqs_n ;
wire [ 3:0] ddr3_dqs_p ;
wire init_calib_complete ;
wire [ 0:0] ddr3_cs_n ;
wire [ 3:0] ddr3_dm ;
wire [ 0:0] ddr3_odt ;
reg test_start ;
initial begin
sclk = 1'b0;
rst_n <= 1'b0;
test_start <= 1'b0;
#(100*`CLOCK);
rst_n <= 1'b1;
@(posedge init_calib_complete)
#(100*`CLOCK);
test_start <= 1'b1;
#(10)
test_start <= 1'b0;
#(100000)
test_start <= 1'b1;
#(10)
test_start <= 1'b0;
end
always #(`CLOCK/2) sclk = ~sclk;
ddr3_top ddr3_top_inst(
//System Interfaces
.sclk (sclk ),
.rst_n (rst_n ),
//DDR3 Interfaces
.ddr3_addr (ddr3_addr ),
.ddr3_ba (ddr3_ba ),
.ddr3_cas_n (ddr3_cas_n ),
.ddr3_ck_n (ddr3_ck_n ),
.ddr3_ck_p (ddr3_ck_p ),
.ddr3_cke (ddr3_cke ),
.ddr3_ras_n (ddr3_ras_n ),
.ddr3_reset_n (ddr3_reset_n ),
.ddr3_we_n (ddr3_we_n ),
.ddr3_dq (ddr3_dq ),
.ddr3_dqs_n (ddr3_dqs_n ),
.ddr3_dqs_p (ddr3_dqs_p ),
.init_calib_complete (init_calib_complete ),
.ddr3_cs_n (ddr3_cs_n ),
.ddr3_dm (ddr3_dm ),
.ddr3_odt (ddr3_odt ),
.test_start (test_start )
);
genvar i;
for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem
ddr3_model u_comp_ddr3(
.rst_n (ddr3_reset_n ),
.ck (ddr3_ck_p ),
.ck_n (ddr3_ck_n ),
.cke (ddr3_cke ),
.cs_n (ddr3_cs_n ),
.ras_n (ddr3_ras_n ),
.cas_n (ddr3_cas_n ),
.we_n (ddr3_we_n ),
.dm_tdqs (ddr3_dm[(2*(i+1)-1):(2*i)] ),
.ba (ddr3_ba ),
.addr (ddr3_addr ),
.dq (ddr3_dq[16*(i+1)-1:16*(i)] ),
.dqs (ddr3_dqs_p[(2*(i+1)-1):(2*i)] ),
.dqs_n (ddr3_dqs_n[(2*(i+1)-1):(2*i)] ),
.tdqs_n ( ),
.odt (ddr3_odt )
);
end
endmodule
我们进行modelsim仿真,得到的实验结果入下:
从上图中,我们可以看到误码个数为零,从而证明了我们程序的正确性,其中上面给出的源码是下板实验的最终代码,只需要稍微调整便可以在moselsim中运行,讲test_start不由vio产生,有tb产生即可。
我们将对应的程序下到开发板中,对应的现象如下图:
从上图中,我们可以看出没错错误的情况,从而验证了我们程序的正确性。