ISE中带有DDR3 的IP核,可以生成MIG,利用用户接口控制DDR3的读写,方便DDR3的使用,其自带的工程提供了例子以及仿真,但是其仿真程序比较复杂,可读性很差,不利用实际掌握DDR3的理解,因此在这里自己编写DDR的读写控制程序,实现DDR3的控制,便于掌握MIG的使用。
主要内容为:
首先如下图所示,建立新的工程
由于有spatan6 开发板,因此工程参数设置如下:
选择IP核产生工具
打开IP核产生工具之后,新建IP核工程,设置好参数之后,选择如下:
建立完成之后,关闭IP核工程。此时我们已经得到了利用IP核工具产生的IP核工程,在如下目录中
下面我们利用生成的代码,自己建立仿真工程对ddr3进行读写
用仿真分析DDR3的读写,需要有三个部分,DDR3存储单元仿真模型、MIG用户接口以及读写模块。
在本次仿真中MIG用户接口由IP核产生,将其导入到ISE工程即可如下图所示。由于改接口不但仿真中可以使用,在实际的工程中也可以使用,因此在immpitation中导入
在之前的ISE工程当中,选择导入用户接口
将该目录下的三个.v文件以及mcb_controller下面的文件导入ISE中的工程如下:
此时,DDR的用户接口以及完成导入。
该文件也已经产生,在sim 目录下,将下图的两个文件导入即可。该文件仅仅供仿真使用,因此在sim中导入两个文件
`timescale 1ps/1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 10:00:35 04/26/2020
// Design Name:
// Module Name: ddr3_drive
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ddr3_drive(
//system signal
input s_clk ,
input s_rst_n ,
//DDR3 User Interface
output wire p0_cmd_en ,
output wire [2:0] p0_cmd_instr ,
output wire[5:0] p0_cmd_bl ,
output wire [29:0] p0_cmd_addr ,
output reg p0_wr_en ,
output wire [7:0] p0_wr_mask ,
output reg [63:0] p0_wr_data ,
//Debug
input wr_trig
);
//========================================================================\
// =========== Define Parameter and Internal signals ===========
//========================================================================/
reg p0_wr_en_r1 ; //用于捕获wr_en的下降沿
//=============================================================================
//************** Main Code **************
//=============================================================================
always @(posedge s_clk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
p0_wr_en <= 'd0;
else if(p0_wr_data >= 'd15)
p0_wr_en <= 'd0;
else if(wr_trig == 1'b1)
p0_wr_en <= 1'b1;
end
always @(posedge s_clk or negedge s_rst_n) begin
if(s_rst_n == 1'b0)
p0_wr_data <= 'd0;
else if(p0_wr_en == 1'b1)
p0_wr_data <= p0_wr_data + 1'b1;
end
always @(posedge s_clk) begin
p0_wr_en_r1 <= p0_wr_en;
end
assign p0_cmd_en = ~p0_wr_en & p0_wr_en_r1;
assign p0_cmd_instr = 3'b000;//write 命令
assign p0_cmd_bl = 'd15; //突发长度
assign p0_cmd_addr = 29'b00000000000000000000001100000; //32位port 地址的后4位为0,表示内存中第几个32位的存储结构
assign p0_wr_mask = 8'b0;
endmodule
建立顶层仿真文件,如下图
建立之后,首先设置DDR3的仿真参数,该部分参数可以从IP核自带的仿真文件中拷贝,如下图
// ========================================================================== //
// Parameters //
// ========================================================================== //
parameter DEBUG_EN = 0;
localparam DBG_WR_STS_WIDTH = 32;
localparam DBG_RD_STS_WIDTH = 32;
localparam C3_P0_PORT_MODE = "BI_MODE";
localparam C3_P1_PORT_MODE = "BI_MODE";
localparam C3_P2_PORT_MODE = "RD_MODE";
localparam C3_P3_PORT_MODE = "RD_MODE";
localparam C3_P4_PORT_MODE = "RD_MODE";
localparam C3_P5_PORT_MODE = "RD_MODE";
localparam C3_PORT_ENABLE = 6'b111111;
localparam C3_PORT_CONFIG = "B32_B32_R32_R32_R32_R32";
parameter C3_MEMCLK_PERIOD = 3200;
parameter C3_RST_ACT_LOW = 0;
parameter C3_INPUT_CLK_TYPE = "SINGLE_ENDED";
parameter C3_NUM_DQ_PINS = 16;
parameter C3_MEM_ADDR_WIDTH = 13;
parameter C3_MEM_BANKADDR_WIDTH = 3;
parameter C3_MEM_ADDR_ORDER = "BANK_ROW_COLUMN";
parameter C3_P0_MASK_SIZE = 4;
parameter C3_P0_DATA_PORT_SIZE = 32;
parameter C3_P1_MASK_SIZE = 4;
parameter C3_P1_DATA_PORT_SIZE = 32;
parameter C3_MEM_BURST_LEN = 8;
parameter C3_MEM_NUM_COL_BITS = 10;
parameter C3_CALIB_SOFT_IP = "TRUE";
parameter C3_SIMULATION = "TRUE";
parameter C3_HW_TESTING = "FALSE";
parameter C3_SMALL_DEVICE = "FALSE";
localparam C3_p0_BEGIN_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p0_DATA_MODE = 4'b0010;
localparam C3_p0_END_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h02ffffff:32'h000002ff;
localparam C3_p0_PRBS_EADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'hfc000000:32'hfffffc00;
localparam C3_p0_PRBS_SADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p1_BEGIN_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h03000000:32'h00000300;
localparam C3_p1_DATA_MODE = 4'b0010;
localparam C3_p1_END_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h04ffffff:32'h000004ff;
localparam C3_p1_PRBS_EADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'hf8000000:32'hfffff800;
localparam C3_p1_PRBS_SADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'h03000000:32'h00000300;
localparam C3_p2_BEGIN_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p2_DATA_MODE = 4'b0010;
localparam C3_p2_END_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h02ffffff:32'h000002ff;
localparam C3_p2_PRBS_EADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'hfc000000:32'hfffffc00;
localparam C3_p2_PRBS_SADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p3_BEGIN_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p3_DATA_MODE = 4'b0010;
localparam C3_p3_END_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h02ffffff:32'h000002ff;
localparam C3_p3_PRBS_EADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'hfc000000:32'hfffffc00;
localparam C3_p3_PRBS_SADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p4_BEGIN_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p4_DATA_MODE = 4'b0010;
localparam C3_p4_END_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h02ffffff:32'h000002ff;
localparam C3_p4_PRBS_EADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'hfc000000:32'hfffffc00;
localparam C3_p4_PRBS_SADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p5_BEGIN_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
localparam C3_p5_DATA_MODE = 4'b0010;
localparam C3_p5_END_ADDRESS = (C3_HW_TESTING == "TRUE") ? 32'h02ffffff:32'h000002ff;
localparam C3_p5_PRBS_EADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'hfc000000:32'hfffffc00;
localparam C3_p5_PRBS_SADDR_MASK_POS = (C3_HW_TESTING == "TRUE") ? 32'h01000000:32'h00000100;
// ========================================================================== //
// Signal Declarations //
// ========================================================================== //
// Clocks
// Clocks
reg c3_sys_clk;
wire c3_sys_clk_p;
wire c3_sys_clk_n;
// System Reset
reg c3_sys_rst;
wire c3_sys_rst_i;
// Design-Top Port Map
wire c3_error;
wire c3_calib_done;
wire [31:0] c3_cmp_data;
wire c3_cmp_error;
wire [C3_MEM_ADDR_WIDTH-1:0] mcb3_dram_a;
wire [C3_MEM_BANKADDR_WIDTH-1:0] mcb3_dram_ba;
wire mcb3_dram_ck;
wire mcb3_dram_ck_n;
wire [C3_NUM_DQ_PINS-1:0] mcb3_dram_dq;
wire mcb3_dram_dqs;
wire mcb3_dram_dqs_n;
wire mcb3_dram_dm;
wire mcb3_dram_ras_n;
wire mcb3_dram_cas_n;
wire mcb3_dram_we_n;
wire mcb3_dram_cke;
wire mcb3_dram_odt;
wire mcb3_dram_reset_n;
wire [64 + (2*C3_P0_DATA_PORT_SIZE - 1):0] c3_p0_error_status;
wire [64 + (2*C3_P1_DATA_PORT_SIZE - 1):0] c3_p1_error_status;
wire [127 : 0] c3_p2_error_status;
wire [127 : 0] c3_p3_error_status;
wire [127 : 0] c3_p4_error_status;
wire [127 : 0] c3_p5_error_status;
wire mcb3_dram_udqs; // for X16 parts
wire mcb3_dram_udqs_n; // for X16 parts
wire mcb3_dram_udm; // for X16 parts
wire c3_vio_modify_enable = 1'b1;
wire [2:0] c3_vio_data_mode_value = 3'b010;
wire [2:0] c3_vio_addr_mode_value = 3'b011;
// User design Sim
wire c3_clk0;
wire c3_rst0;
reg c3_aresetn;
wire c3_wrap_en;
wire c3_cmd_err;
wire c3_data_msmatch_err;
wire c3_write_err;
wire c3_read_err;
wire c3_test_cmptd;
wire c3_dbg_wr_sts_vld;
wire c3_dbg_rd_sts_vld;
wire [DBG_WR_STS_WIDTH-1:0] c3_dbg_wr_sts;
wire [DBG_WR_STS_WIDTH-1:0] c3_dbg_rd_sts;
wire c3_p0_cmd_en;
wire [2:0] c3_p0_cmd_instr;
wire [5:0] c3_p0_cmd_bl;
wire [29:0] c3_p0_cmd_byte_addr;
wire c3_p0_cmd_empty;
wire c3_p0_cmd_full;
wire c3_p0_wr_en;
wire [C3_P0_MASK_SIZE - 1:0] c3_p0_wr_mask;
wire [C3_P0_DATA_PORT_SIZE - 1:0] c3_p0_wr_data;
wire c3_p0_wr_full;
wire c3_p0_wr_empty;
wire [6:0] c3_p0_wr_count;
wire c3_p0_wr_underrun;
wire c3_p0_wr_error;
wire c3_p0_rd_en;
wire [C3_P0_DATA_PORT_SIZE - 1:0] c3_p0_rd_data;
wire c3_p0_rd_full;
wire c3_p0_rd_empty;
wire [6:0] c3_p0_rd_count;
wire c3_p0_rd_overflow;
wire c3_p0_rd_error;
wire c3_p1_cmd_en;
wire [2:0] c3_p1_cmd_instr;
wire [5:0] c3_p1_cmd_bl;
wire [29:0] c3_p1_cmd_byte_addr;
wire c3_p1_cmd_empty;
wire c3_p1_cmd_full;
wire c3_p1_wr_en;
wire [C3_P1_MASK_SIZE - 1:0] c3_p1_wr_mask;
wire [C3_P1_DATA_PORT_SIZE - 1:0] c3_p1_wr_data;
wire c3_p1_wr_full;
wire c3_p1_wr_empty;
wire [6:0] c3_p1_wr_count;
wire c3_p1_wr_underrun;
wire c3_p1_wr_error;
wire c3_p1_rd_en;
wire [C3_P1_DATA_PORT_SIZE - 1:0] c3_p1_rd_data;
wire c3_p1_rd_full;
wire c3_p1_rd_empty;
wire [6:0] c3_p1_rd_count;
wire c3_p1_rd_overflow;
wire c3_p1_rd_error;
wire c3_p2_cmd_en;
wire [2:0] c3_p2_cmd_instr;
wire [5:0] c3_p2_cmd_bl;
wire [29:0] c3_p2_cmd_byte_addr;
wire c3_p2_cmd_empty;
wire c3_p2_cmd_full;
wire c3_p2_rd_en;
wire [31:0] c3_p2_rd_data;
wire c3_p2_rd_full;
wire c3_p2_rd_empty;
wire [6:0] c3_p2_rd_count;
wire c3_p2_rd_overflow;
wire c3_p2_rd_error;
wire c3_p3_cmd_en;
wire [2:0] c3_p3_cmd_instr;
wire [5:0] c3_p3_cmd_bl;
wire [29:0] c3_p3_cmd_byte_addr;
wire c3_p3_cmd_empty;
wire c3_p3_cmd_full;
wire c3_p3_rd_en;
wire [31:0] c3_p3_rd_data;
wire c3_p3_rd_full;
wire c3_p3_rd_empty;
wire [6:0] c3_p3_rd_count;
wire c3_p3_rd_overflow;
wire c3_p3_rd_error;
wire c3_p4_cmd_en;
wire [2:0] c3_p4_cmd_instr;
wire [5:0] c3_p4_cmd_bl;
wire [29:0] c3_p4_cmd_byte_addr;
wire c3_p4_cmd_empty;
wire c3_p4_cmd_full;
wire c3_p4_rd_en;
wire [31:0] c3_p4_rd_data;
wire c3_p4_rd_full;
wire c3_p4_rd_empty;
wire [6:0] c3_p4_rd_count;
wire c3_p4_rd_overflow;
wire c3_p4_rd_error;
wire c3_p5_cmd_en;
wire [2:0] c3_p5_cmd_instr;
wire [5:0] c3_p5_cmd_bl;
wire [29:0] c3_p5_cmd_byte_addr;
wire c3_p5_cmd_empty;
wire c3_p5_cmd_full;
wire c3_p5_rd_en;
wire [31:0] c3_p5_rd_data;
wire c3_p5_rd_full;
wire c3_p5_rd_empty;
wire [6:0] c3_p5_rd_count;
wire c3_p5_rd_overflow;
wire c3_p5_rd_error;
wire c3_p2_wr_clk;
wire c3_p2_wr_en;
wire[3:0] c3_p2_wr_mask;
wire[31:0] c3_p2_wr_data;
wire c3_p2_wr_full;
wire c3_p2_wr_empty;
wire[6:0] c3_p2_wr_count;
wire c3_p2_wr_underrun;
wire c3_p2_wr_error;
wire c3_p3_wr_clk;
wire c3_p3_wr_en;
wire[3:0] c3_p3_wr_mask;
wire[31:0] c3_p3_wr_data;
wire c3_p3_wr_full;
wire c3_p3_wr_empty;
wire[6:0] c3_p3_wr_count;
wire c3_p3_wr_underrun;
wire c3_p3_wr_error;
wire c3_p4_wr_clk;
wire c3_p4_wr_en;
wire[3:0] c3_p4_wr_mask;
wire[31:0] c3_p4_wr_data;
wire c3_p4_wr_full;
wire c3_p4_wr_empty;
wire[6:0] c3_p4_wr_count;
wire c3_p4_wr_underrun;
wire c3_p4_wr_error;
wire c3_p5_wr_clk;
wire c3_p5_wr_en;
wire[3:0] c3_p5_wr_mask;
wire[31:0] c3_p5_wr_data;
wire c3_p5_wr_full;
wire c3_p5_wr_empty;
wire[6:0] c3_p5_wr_count;
wire c3_p5_wr_underrun;
wire c3_p5_wr_error;
// Error & Calib Signals
wire error;
wire calib_done;
wire rzq3; wire zio3;
// ========================================================================== //
// Clocks Generation //
// ========================================================================== //
initial
c3_sys_clk = 1'b0;
always
#(C3_MEMCLK_PERIOD/2) c3_sys_clk = ~c3_sys_clk;
assign c3_sys_clk_p = c3_sys_clk;
assign c3_sys_clk_n = ~c3_sys_clk;
// ========================================================================== //
// Reset Generation //
// ========================================================================== //
initial begin
c3_sys_rst = 1'b0;
#20000;
c3_sys_rst = 1'b1;
end
assign c3_sys_rst_i = C3_RST_ACT_LOW ? c3_sys_rst : ~c3_sys_rst;
// ========================================================================== //
// Error Grouping //
// ========================================================================== //
assign error = c3_error;
assign calib_done = c3_calib_done;
// The PULLDOWN component is connected to the ZIO signal primarily to avoid the
// unknown state in simulation. In real hardware, ZIO should be a no connect(NC) pin.
PULLDOWN zio_pulldown3 (.O(zio3)); PULLDOWN rzq_pulldown3 (.O(rzq3));
// ========================================================================== //
// DESIGN TOP INSTANTIATION //
// ========================================================================== //
DDR3_wyz #(
.C3_P0_MASK_SIZE (C3_P0_MASK_SIZE ),
.C3_P0_DATA_PORT_SIZE (C3_P0_DATA_PORT_SIZE ),
.C3_P1_MASK_SIZE (C3_P1_MASK_SIZE ),
.C3_P1_DATA_PORT_SIZE (C3_P1_DATA_PORT_SIZE ),
.C3_MEMCLK_PERIOD (C3_MEMCLK_PERIOD),
.C3_RST_ACT_LOW (C3_RST_ACT_LOW),
.C3_INPUT_CLK_TYPE (C3_INPUT_CLK_TYPE),
.DEBUG_EN (DEBUG_EN),
.C3_MEM_ADDR_ORDER (C3_MEM_ADDR_ORDER ),
.C3_NUM_DQ_PINS (C3_NUM_DQ_PINS ),
.C3_MEM_ADDR_WIDTH (C3_MEM_ADDR_WIDTH ),
.C3_MEM_BANKADDR_WIDTH (C3_MEM_BANKADDR_WIDTH),
.C3_SIMULATION (C3_SIMULATION),
.C3_CALIB_SOFT_IP (C3_CALIB_SOFT_IP )
)
design_top (
.c3_sys_clk (c3_sys_clk),
.c3_sys_rst_i (c3_sys_rst_i),
.mcb3_dram_dq (mcb3_dram_dq),
.mcb3_dram_a (mcb3_dram_a),
.mcb3_dram_ba (mcb3_dram_ba),
.mcb3_dram_ras_n (mcb3_dram_ras_n),
.mcb3_dram_cas_n (mcb3_dram_cas_n),
.mcb3_dram_we_n (mcb3_dram_we_n),
.mcb3_dram_odt (mcb3_dram_odt),
.mcb3_dram_cke (mcb3_dram_cke),
.mcb3_dram_ck (mcb3_dram_ck),
.mcb3_dram_ck_n (mcb3_dram_ck_n),
.mcb3_dram_dqs (mcb3_dram_dqs),
.mcb3_dram_dqs_n (mcb3_dram_dqs_n),
.mcb3_dram_udqs (mcb3_dram_udqs), // for X16 parts
.mcb3_dram_udqs_n (mcb3_dram_udqs_n), // for X16 parts
.mcb3_dram_udm (mcb3_dram_udm), // for X16 parts
.mcb3_dram_dm (mcb3_dram_dm),
.mcb3_dram_reset_n (mcb3_dram_reset_n),
.c3_clk0 (c3_clk0),
.c3_rst0 (c3_rst0),
.c3_calib_done (c3_calib_done),
.mcb3_rzq (rzq3),
.mcb3_zio (zio3),
.c3_p0_cmd_clk (c3_clk0),
.c3_p0_cmd_en (c3_p0_cmd_en),
.c3_p0_cmd_instr (c3_p0_cmd_instr),
.c3_p0_cmd_bl (c3_p0_cmd_bl),
.c3_p0_cmd_byte_addr (c3_p0_cmd_byte_addr),
.c3_p0_cmd_empty (c3_p0_cmd_empty),
.c3_p0_cmd_full (c3_p0_cmd_full),
.c3_p0_wr_clk (c3_clk0),
.c3_p0_wr_en (c3_p0_wr_en),
.c3_p0_wr_mask (c3_p0_wr_mask),
.c3_p0_wr_data (c3_p0_wr_data),
.c3_p0_wr_full (c3_p0_wr_full),
.c3_p0_wr_empty (c3_p0_wr_empty),
.c3_p0_wr_count (c3_p0_wr_count),
.c3_p0_wr_underrun (c3_p0_wr_underrun),
.c3_p0_wr_error (c3_p0_wr_error),
.c3_p0_rd_clk (c3_clk0),
.c3_p0_rd_en (c3_p0_rd_en),
.c3_p0_rd_data (c3_p0_rd_data),
.c3_p0_rd_full (c3_p0_rd_full),
.c3_p0_rd_empty (c3_p0_rd_empty),
.c3_p0_rd_count (c3_p0_rd_count),
.c3_p0_rd_overflow (c3_p0_rd_overflow),
.c3_p0_rd_error (c3_p0_rd_error),
.c3_p1_cmd_clk (c3_clk0),
.c3_p1_cmd_en (c3_p1_cmd_en),
.c3_p1_cmd_instr (c3_p1_cmd_instr),
.c3_p1_cmd_bl (c3_p1_cmd_bl),
.c3_p1_cmd_byte_addr (c3_p1_cmd_byte_addr),
.c3_p1_cmd_empty (c3_p1_cmd_empty),
.c3_p1_cmd_full (c3_p1_cmd_full),
.c3_p1_wr_clk (c3_clk0),
.c3_p1_wr_en (c3_p1_wr_en),
.c3_p1_wr_mask (c3_p1_wr_mask),
.c3_p1_wr_data (c3_p1_wr_data),
.c3_p1_wr_full (c3_p1_wr_full),
.c3_p1_wr_empty (c3_p1_wr_empty),
.c3_p1_wr_count (c3_p1_wr_count),
.c3_p1_wr_underrun (c3_p1_wr_underrun),
.c3_p1_wr_error (c3_p1_wr_error),
.c3_p1_rd_clk (c3_clk0),
.c3_p1_rd_en (c3_p1_rd_en),
.c3_p1_rd_data (c3_p1_rd_data),
.c3_p1_rd_full (c3_p1_rd_full),
.c3_p1_rd_empty (c3_p1_rd_empty),
.c3_p1_rd_count (c3_p1_rd_count),
.c3_p1_rd_overflow (c3_p1_rd_overflow),
.c3_p1_rd_error (c3_p1_rd_error),
.c3_p2_cmd_clk (c3_clk0),
.c3_p2_cmd_en (c3_p2_cmd_en),
.c3_p2_cmd_instr (c3_p2_cmd_instr),
.c3_p2_cmd_bl (c3_p2_cmd_bl),
.c3_p2_cmd_byte_addr (c3_p2_cmd_byte_addr),
.c3_p2_cmd_empty (c3_p2_cmd_empty),
.c3_p2_cmd_full (c3_p2_cmd_full),
.c3_p2_rd_clk (c3_clk0),
.c3_p2_rd_en (c3_p2_rd_en),
.c3_p2_rd_data (c3_p2_rd_data),
.c3_p2_rd_full (c3_p2_rd_full),
.c3_p2_rd_empty (c3_p2_rd_empty),
.c3_p2_rd_count (c3_p2_rd_count),
.c3_p2_rd_overflow (c3_p2_rd_overflow),
.c3_p2_rd_error (c3_p2_rd_error),
.c3_p3_cmd_clk (c3_clk0),
.c3_p3_cmd_en (c3_p3_cmd_en),
.c3_p3_cmd_instr (c3_p3_cmd_instr),
.c3_p3_cmd_bl (c3_p3_cmd_bl),
.c3_p3_cmd_byte_addr (c3_p3_cmd_byte_addr),
.c3_p3_cmd_empty (c3_p3_cmd_empty),
.c3_p3_cmd_full (c3_p3_cmd_full),
.c3_p3_rd_clk (c3_clk0),
.c3_p3_rd_en (c3_p3_rd_en),
.c3_p3_rd_data (c3_p3_rd_data),
.c3_p3_rd_full (c3_p3_rd_full),
.c3_p3_rd_empty (c3_p3_rd_empty),
.c3_p3_rd_count (c3_p3_rd_count),
.c3_p3_rd_overflow (c3_p3_rd_overflow),
.c3_p3_rd_error (c3_p3_rd_error),
.c3_p4_cmd_clk (c3_clk0),
.c3_p4_cmd_en (c3_p4_cmd_en),
.c3_p4_cmd_instr (c3_p4_cmd_instr),
.c3_p4_cmd_bl (c3_p4_cmd_bl),
.c3_p4_cmd_byte_addr (c3_p4_cmd_byte_addr),
.c3_p4_cmd_empty (c3_p4_cmd_empty),
.c3_p4_cmd_full (c3_p4_cmd_full),
.c3_p4_rd_clk (c3_clk0),
.c3_p4_rd_en (c3_p4_rd_en),
.c3_p4_rd_data (c3_p4_rd_data),
.c3_p4_rd_full (c3_p4_rd_full),
.c3_p4_rd_empty (c3_p4_rd_empty),
.c3_p4_rd_count (c3_p4_rd_count),
.c3_p4_rd_overflow (c3_p4_rd_overflow),
.c3_p4_rd_error (c3_p4_rd_error),
.c3_p5_cmd_clk (c3_clk0),
.c3_p5_cmd_en (c3_p5_cmd_en),
.c3_p5_cmd_instr (c3_p5_cmd_instr),
.c3_p5_cmd_bl (c3_p5_cmd_bl),
.c3_p5_cmd_byte_addr (c3_p5_cmd_byte_addr),
.c3_p5_cmd_empty (c3_p5_cmd_empty),
.c3_p5_cmd_full (c3_p5_cmd_full),
.c3_p5_rd_clk (c3_clk0),
.c3_p5_rd_en (c3_p5_rd_en),
.c3_p5_rd_data (c3_p5_rd_data),
.c3_p5_rd_full (c3_p5_rd_full),
.c3_p5_rd_empty (c3_p5_rd_empty),
.c3_p5_rd_count (c3_p5_rd_count),
.c3_p5_rd_overflow (c3_p5_rd_overflow),
.c3_p5_rd_error (c3_p5_rd_error)
);
ddr3_writeandread ddr3_drive_inst(
.s_clk (c3_clk0),
.s_rst_n (~c3_rst0),
.p0_cmd_en (c3_p0_cmd_en),
.p0_cmd_instr (c3_p0_cmd_instr),
.p0_cmd_bl (c3_p0_cmd_bl),
.p0_cmd_addr (c3_p0_cmd_byte_addr),
///.p0_cmd_full (c3_p0_cmd_full),
// User Port-0 data write interface will be active only when the port is enabled in
// the port configurations Config-1, Config-2, Config-3, Config-4 and Config-5
.p0_wr_en (c3_p0_wr_en),
.p0_wr_mask (c3_p0_wr_mask),
.p0_wr_data (c3_p0_wr_data),
//.p0_wr_full (c3_p0_wr_full),
//.p0_wr_fifo_counts (c3_p0_wr_count),
.wr_trig (wr_trig)
);
DDR3存储器例化
该部分的例化参考官方的仿真文件,例化过程如下:
// ========================================================================== //
// Memory model instances //
// ========================================================================== //
generate
if(C3_NUM_DQ_PINS == 16) begin : MEM_INST3
ddr3_model_c3 u_mem_c3(
.ck (mcb3_dram_ck),
.ck_n (mcb3_dram_ck_n),
.cke (mcb3_dram_cke),
.cs_n (1'b0),
.ras_n (mcb3_dram_ras_n),
.cas_n (mcb3_dram_cas_n),
.we_n (mcb3_dram_we_n),
.dm_tdqs ({mcb3_dram_udm,mcb3_dram_dm}),
.ba (mcb3_dram_ba),
.addr (mcb3_dram_a),
.dq (mcb3_dram_dq),
.dqs ({mcb3_dram_udqs,mcb3_dram_dqs}),
.dqs_n ({mcb3_dram_udqs_n,mcb3_dram_dqs_n}),
.tdqs_n (),
.odt (mcb3_dram_odt),
.rst_n (mcb3_dram_reset_n)
);
end else begin
ddr3_model_c3 u_mem_c3(
.ck (mcb3_dram_ck),
.ck_n (mcb3_dram_ck_n),
.cke (mcb3_dram_cke),
.cs_n (1'b0),
.ras_n (mcb3_dram_ras_n),
.cas_n (mcb3_dram_cas_n),
.we_n (mcb3_dram_we_n),
.dm_tdqs (mcb3_dram_dm),
.ba (mcb3_dram_ba),
.addr (mcb3_dram_a),
.dq (mcb3_dram_dq),
.dqs (mcb3_dram_dqs),
.dqs_n (mcb3_dram_dqs_n),
.tdqs_n (),
.odt (mcb3_dram_odt),
.rst_n (mcb3_dram_reset_n)
);
End
initial begin
wr_trig = 0;
@(posedge c3_calib_done)//DDR3上电之后自检
#1000;//10ns
wr_trig = 1;//自检之后触发写使能信号,实际上该信号是wr_en的作用
#25600;
wr_trig = 0;
end
再用户读写程序中设置读写的地址以及读写的数据等参数,
assign p0_cmd_bl = 'd15; //突发长度
assign p0_cmd_addr = 29'b00000000000000000000011100000; //32位port 地址的后4位为0忽略,表示内存中第几个32位的存储结构,因为每次读写都是32位,因此地址总线的后4为忽略
因此实际地址表示为70,与下图仿真结果一致。
再modelsim中的Memory list可以看出此时的数据分布为:128位为一组(2^7),因此这个存储结果中的地址表示地址总线的前23位置(29-(7-1))=23