DDR3 MIG IP核仿真与学习

news/2024/11/17 12:52:06/

MIG IP核介绍

在Xilinx系列的FPGA中,为了方便用户对DDR进行读写,官方提供了用于访问DDR的IP核MIG,全称为Memory Interface Generator,具体可参考赛灵思官方文档参考手册:ug586(7 Series Devices Memory Interface Solutions v4.1)。下图是MIG IP核的架构,从图中可以看出,MIG主要有面向用户的端口和面向DDR的端口,用户通过使用MIG能够通过用户端口的信号,来完成对DDR SDRAM的访问,达到简化操作的目的。
在这里插入图片描述
在本文中,我们仅关注某些面向用户的端口,即以下端口:
clk,rst
app_addr,app_cmd,app_en,app_rdy
app_wdf_wren,app_wdf_end,app_wdf_rdy,app_wdf_data
app_rd_data,app_rd_data_valid
其中,第一行信号为全局的时钟和复位信号,第二行信号为命令通道信号,用于发出读写命令,第三行信号为写数据通道信号,最后一行信号为读数据通道信号。

命令通道

在这里插入图片描述
如上图所示,app_cmd用于指定是何命令,3’b000为写命令,而3’b001为读命令,app_addr为相应的读写地址,命令只会在app_en和app_rdy同时为高时,才会被接受。

读数据通道

在这里插入图片描述

如上图所示,读数据的时序比较简单,当读命令发出后,过若干时钟周期,app_rd_data_valid信号便会拉高,此时对应的app_rd_data就是读出的数据。

写数据通道

在这里插入图片描述
在这里插入图片描述

上图是一张MIG控制器的写时序图和官方对这几种写操作的解释,通过官方文档的介绍我们可以知道写入的数据可以在写命令给出之前,之时或者之后给出,但是在写命令之后给出的写数据不能超过两个时钟周期。在写命令之前给出写数据则没有这些限制。之所以能过这样操作,是因为在IP核内部有写入数据的FIFO能够对数据实现缓冲。
在本文中,我们采用1这种方式的数据写入

DDR3 MIG实验

在本实验中,我们实现了一个接口转换:将MIG用户侧的app_*接口信号转化为AXI4接口信号,以供用户更方便的进行调用。
转化的代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/01/03 10:38:32
// Design Name: 
// Module Name: mig2axi4
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module mig2axi4(
//AXI4接口
//全局信号
input logic ACLK,
input logic ARESETn,
//读地址通道
input logic [31:0] ARADDR,
input logic [7:0] ARLEN,
input logic [2:0] ARSIZE,               //2^7=128
input logic [1:0] ARBURST,
input logic [2:0] ARPROT,
input logic ARVALID,
output logic ARREADY,
//读数据通道
output logic RVALID,
output logic [127:0] RDATA,
output logic [1:0] RRESP,
output logic RLAST,
input logic RREADY,
//写地址通道                 
input logic [31:0] AWADDR,
input logic [7:0] AWLEN,
input logic [2:0] AWSIZE,
input logic [1:0] AWBURST,
input logic [2:0] AWPROT,            
input logic AWVALID,
output logic AWREADY,
//写数据通道
input logic [127:0]WDATA,
input logic [15:0] WSTRB,
input logic WLAST,
input logic WVALID,
output logic WREADY,
//写应答通道
output logic [1:0] BRESP,
output logic BVALID,
input logic BREADY,
//MIG侧接口        
input  logic ui_clk,                
input  logic ui_clk_sync_rst,       
input  logic init_calib_complete,   
input  logic app_rdy,               
input  logic app_wdf_rdy,           
input  logic app_rd_data_valid,     
input  logic [127:0]   app_rd_data,           
output logic [27:0]    app_addr,                                 
output logic app_en,                
output logic app_wdf_wren,          
output logic app_wdf_end,           
output logic [2:0]     app_cmd,               //3'b000为写数据,3'b001为读数据           
output logic [127:0]   app_wdf_data);logic [31:0] rd_base_addr;                       //地址每次递增128/16=8
logic [8:0]  rd_len;
logic [31:0] wr_base_addr;
logic [8:0] wr_len;
logic [127:0] rd_buffer [0:255];                  //读数据缓存
logic [31:0] rd_cnt;                              //数据缓存中数据个数
logic [31:0] rd_cmd_cnt;                          //读命令个数
logic [31:0] wr_cnt;                             
logic [31:0] send_cnt;                            //数据发送个数
typedef enum bit [7:0] { IDLE,READ,WRITE
} State;
State cur_state,next_state;
//cur_state
always_ff@(posedge ACLK,negedge ARESETn)
if(!ARESETn)cur_state<=IDLE;
elsecur_state<=next_state;
//next_state
always_comb
begincase(cur_state)IDLE:if(ARVALID)next_state=READ;else if(AWVALID)next_state=WRITE;elsenext_state=IDLE;WRITE:if(BVALID&&BREADY&&BRESP==2'b00)next_state=IDLE;elsenext_state=WRITE;READ:if(RVALID&&RREADY&&RLAST)          //最后一个数据读取完成next_state=IDLE;elsenext_state=READ;default:next_state=IDLE;endcase
end
/********************************************************读数据***************************************************/
//ARREADY
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)ARREADY<=0;
else if(ARVALID&&~ARREADY)ARREADY<=1;
else if(ARREADY&&ARVALID)                       //读地址通道握手完成ARREADY<=0;
//rd_base_addr
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)rd_base_addr<=0;
else if(ARVALID&&ARREADY)rd_base_addr<=ARADDR;
//rd_len
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)rd_len<=0;
else if(ARVALID&&ARREADY)rd_len<=ARLEN+1;
//app_cmd
always_comb
if(cur_state==WRITE)app_cmd=3'b000;
else if(cur_state==READ)app_cmd=3'b001;
elseapp_cmd=3'b000;
//app_en
always_comb
case(cur_state)IDLE:app_en=0;READ:if(rd_cmd_cnt<rd_len&&app_rdy)                 //app_rdy为高且读命令次数还未到rd_lenapp_en=1;elseapp_en=0;WRITE:if(app_rdy&&app_wdf_rdy&&WVALID)               //DDR准备好接受数据,并且WDATA有效时,拉高app_en                 app_en=1;elseapp_en=0;default:app_en=0;
endcase
//app_addr
always_ff@(posedge ACLK)
if(ARVALID&&ARREADY)app_addr<=ARADDR;
else if(AWVALID&&AWREADY)app_addr<=AWADDR;
else if(app_en&&app_rdy)                               //写数据成功或者读命令发送成功app_addr<=app_addr+8;
//rd_cmd_cnt
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)rd_cmd_cnt<=0;
else if(cur_state==READ&&app_en&&app_rdy)      //发出一次读命令rd_cmd_cnt<=rd_cmd_cnt+1;
else if(cur_state==IDLE)rd_cmd_cnt<=0;
//rd_cnt
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)rd_cnt<=0;
else if(app_rd_data_valid)rd_cnt<=rd_cnt+1;
else if(cur_state==IDLE)rd_cnt<=0;
//rd_buffer
always_ff@(posedge ACLK)
if(app_rd_data_valid)rd_buffer[rd_cnt]<=app_rd_data;                                                //数据缓存
//send_cnt
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)send_cnt<=0;
else if(ARVALID&&ARREADY)send_cnt<=0;
else if(rd_cnt==rd_len&&RVALID&&RREADY)                                         //数据缓存完毕send_cnt<=send_cnt+1;
else if(cur_state==IDLE)send_cnt<=0;
//RVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)RVALID<=0;
else if(rd_cnt==rd_len&&RVALID&&RREADY&&RLAST)                    //之后send_cnt==rd_len                        RVALID<=0;
else if(rd_cnt==rd_len&&send_cnt<rd_len)                          RVALID<=1;
//RDATA
always_combRDATA=rd_buffer[send_cnt];
//RLAST
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)RLAST<=0;
else if(send_cnt==rd_len-2&&RVALID&&RREADY)                        //倒数第二个数据发送完成,拉高RLAST,表明下一个数据是最后一个数据RLAST<=1;
else if(send_cnt==rd_len-1&&RVALID&&RREADY&&RLAST)                 //最后一个数据发送完成,拉低RLASTRLAST<=0;
/***************************************************************************写数据*******************************************************************/
//awready
always_ff @(posedge ACLK) 
begin    if(~ARESETn)AWREADY<=0;else if(AWVALID&&~AWREADY)AWREADY<=1;else if(AWVALID&&AWREADY)                //写地址通道握手完成AWREADY<=0;
end
//wr_len
always_ff@(posedge ACLK)
if(AWVALID&&AWREADY)wr_len<=AWLEN+1;
//wr_base_addr
always_ff@(posedge ACLK)
if(AWVALID&&AWREADY)wr_base_addr<=AWADDR;
//app_wdf_wren                                   若app_rdy和app_wdf_rdy以及WVALID均为高,则拉高app_wdf_wren和wready         (WVALID为高说明数据有效,app_rdy和app_wdf_rdy为高说明DDR可写入数据)
always_comb
if(cur_state==WRITE&&app_rdy&&app_wdf_rdy&&WVALID)app_wdf_wren=1;
elseapp_wdf_wren=0;
//wready
assign WREADY=app_wdf_wren;
//app_wdf_end
assign app_wdf_end=app_wdf_wren;
//app_wdf_data
assign app_wdf_data=WDATA;
//BRESP
assign BRESP=2'b00;         //OK
//BVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)BVALID<=0;
else if(WVALID&&WREADY&&WLAST)            //最后一个数据写入完成后拉高BVALIDBVALID<=1;
else if(BVALID&&BREADY&&BRESP==2'b00)     //写响应通道握手完成BVALID<=0;
//BID
endmodule

我们通过MIG IP提供的DDR3仿真模型进行仿真,如下图所示,只需添加ddr3_model.svddr3_model_parameters.vh文件至仿真平台即可。
在这里插入图片描述
在这里插入图片描述
下面的代码用于产生AXI4测试信号:
axi4_master.sv

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/01/03 12:56:25
// Design Name: 
// Module Name: axi4_master
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module axi4_master(
input logic ACLK,
input logic ARESETn,
//读地址通道
output logic [31:0] ARADDR,
output logic [7:0] ARLEN,
output logic ARVALID,
input logic ARREADY,
//读数据通道
input logic [127:0] RDATA,
input logic [1:0] RRESP,
input logic RLAST,
input logic RVALID,
output logic RREADY,
//写地址通道                 
output logic [31:0] AWADDR,
output logic [7:0] AWLEN,              
output logic AWVALID,
input logic AWREADY,
//写数据通道
output logic [127:0] WDATA,
output logic [15:0] WSTRB,
output logic WLAST,
output logic WVALID,
input logic WREADY,
//写应答通道
input logic [1:0] BRESP,
input logic BVALID,
output logic BREADY,
//初始化完成信号
input  logic init_calib_complete  );
parameter WRITE_BASE_ADDR = 256;
parameter READ_BASE_ADDR = 256;
parameter TEST_LEN = 32-1;
logic init_calib_complete_d1;
logic start;
logic [31:0] wr_cnt;
logic [31:0] rd_cnt;
//start
assign start=init_calib_complete&(~init_calib_complete_d1);
//init_calib_complete_d1
always_ff@(posedge ACLK)init_calib_complete_d1<=init_calib_complete;
//写16个数据
//AWADDR
assign AWADDR=WRITE_BASE_ADDR;
//AWLEN
assign AWLEN=TEST_LEN;
//AWVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)AWVALID<=0;
else if(start)AWVALID<=1;
else if(AWVALID&&AWREADY)AWVALID<=0;
//WDATA
always_combWDATA=wr_cnt;
//WSTRB
assign WSTRB=16'hffff;
//WLAST
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)WLAST<=0;
else if(WVALID&&WREADY&&wr_cnt==TEST_LEN+1-2)            //倒数第二个数据写入完成WLAST<=1;
else if(WVALID&&WREADY&&WLAST)                         //最后一个数据传输完成WLAST<=0;
//WVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)WVALID<=0;
else if(AWVALID&&AWREADY)WVALID<=1;
else if(WVALID&&WREADY&&WLAST)WVALID<=0;
//BREADY
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)BREADY<=0;
else if(AWVALID&&AWREADY)BREADY<=1;
else if(BVALID&&BREADY&&BRESP==2'b00)BREADY<=0;
//wr_cnt
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)wr_cnt<=0;
else if(start)wr_cnt<=0;
else if(WVALID&&WREADY)wr_cnt<=wr_cnt+1;
//读16个数据
//ARADDR
assign ARADDR=READ_BASE_ADDR;
//ARLEN
assign  ARLEN=TEST_LEN;
//ARVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)ARVALID<=0;
else if(BVALID&&BREADY)ARVALID<=1;
else if(ARVALID&&ARREADY)ARVALID<=0;
//rready
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)RREADY<=0;
else if(ARVALID&&ARREADY)RREADY<=1;
else if(RVALID&&RREADY&&RLAST)RREADY<=0;endmodule

整个工程的顶层文件top.sv为:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/01/03 14:22:32
// Design Name: 
// Module Name: top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module top(
input              sys_clk,         //ϵͳʱ��
input              sys_rst_n,       //��λ,����Ч
// DDR3
inout [15:0]       ddr3_dq,         //DDR3 ����
inout [1:0]        ddr3_dqs_n,      //DDR3 dqs��
inout [1:0]        ddr3_dqs_p,      //DDR3 dqs��       
output [13:0]      ddr3_addr,       //DDR3 ��ַ
output [2:0]       ddr3_ba,         //DDR3 banck ѡ��
output             ddr3_ras_n,      //DDR3 ��ѡ��
output             ddr3_cas_n,      //DDR3 ��ѡ��
output             ddr3_we_n,       //DDR3 ��дѡ��
output             ddr3_reset_n,    //DDR3 ��λ
output [0:0]       ddr3_ck_p,       //DDR3 ʱ����
output [0:0]       ddr3_ck_n,       //DDR3 ʱ�Ӹ�
output [0:0]       ddr3_cke,        //DDR3 ʱ��ʹ��
output [0:0]       ddr3_cs_n,       //DDR3 Ƭѡ
output [1:0]       ddr3_dm,         //DDR3_dm
output [0:0]       ddr3_odt         //DDR3_odt);//axi接口
logic ACLK;
logic ARESETn;
//读地址通道
logic [31:0] ARADDR;
logic [7:0] ARLEN;
logic ARVALID;
logic ARREADY;
//读数据通道
logic [127:0] RDATA;
logic [1:0] RRESP;
logic RLAST;
logic RVALID;
logic RREADY;
//写地址通道
logic [31:0] AWADDR;
logic [7:0] AWLEN;
logic AWVALID;
logic AWREADY;
//写数据通道
logic [127:0] WDATA;
logic [15:0] WSTRB;
logic WLAST;
logic WVALID;
logic WREADY;
//写应答通道
logic [1:0] BRESP;
logic BVALID;
logic BREADY;
//mig接口
logic app_rdy;               
logic app_wdf_rdy;           
logic app_rd_data_valid;     
logic [127:0] app_rd_data;           
logic [27:0] app_addr;                                 
logic app_en;                
logic app_wdf_wren;          
logic app_wdf_end;           
logic [2:0] app_cmd;               //3'b000为写数据,3'b001为读数据           
logic [127:0] app_wdf_data;
logic init_calib_complete;
//
logic clk_200;
logic ui_clk;
logic ui_clk_sync_rst;
logic locked;
//
assign ACLK=ui_clk;
assign ARESETn=~ui_clk_sync_rst;        
//ddr侧信号
// logic ddr3_addr                      (ddr3_addr),   // output [14:0]	ddr3_addr
// logic ddr3_ba                        (ddr3_ba),     // output [2:0]	ddr3_ba
// logic ddr3_cas_n                     (ddr3_cas_n),  // output		ddr3_cas_n
// logic ddr3_ck_n                      (ddr3_ck_n),   // output [0:0]	ddr3_ck_n
// logic ddr3_ck_p                      (ddr3_ck_p),   // output [0:0]	ddr3_ck_p
// logic ddr3_cke                       (ddr3_cke),    // output [0:0]	ddr3_cke
// logic ddr3_ras_n                     (ddr3_ras_n),  // output		ddr3_ras_n
// logic ddr3_reset_n                   (ddr3_reset_n),// output		ddr3_reset_n
// logic ddr3_we_n                      (ddr3_we_n),   // output		ddr3_we_n
// logic ddr3_dq                        (ddr3_dq),     // inout [31:0]	ddr3_dq
// logic ddr3_dqs_n                     (ddr3_dqs_n),  // inout [3:0]	ddr3_dqs_n
// logic ddr3_dqs_p                     (ddr3_dqs_p),  // inout [3:0]	ddr3_dqs_p
// logic ddr3_cs_n                      (ddr3_cs_n),   // output [0:0]	ddr3_cs_n
// logic ddr3_dm                        (ddr3_dm),     // output [3:0]	ddr3_dm
// logic ddr3_odt                       (ddr3_odt),    // output [0:0]	ddr3_odt//模块例化
axi4_master U1(
.ACLK(ACLK),
.ARESETn(ARESETn),
//读地址通道
.ARADDR(ARADDR),
.ARLEN(ARLEN),
.ARVALID(ARVALID),
.ARREADY(ARREADY),
//读数据通道
.RVALID(RVALID),
.RDATA(RDATA),
.RRESP(RRESP),
.RLAST(RLAST),
.RREADY(RREADY),
//写地址通道                 
.AWADDR(AWADDR),
.AWLEN(AWLEN),              
.AWVALID(AWVALID),
.AWREADY(AWREADY),
//写数据通道
.WDATA(WDATA),
.WSTRB(WSTRB),
.WLAST(WLAST),
.WVALID(WVALID),
.WREADY(WREADY),
//写应答通道
.BRESP(BRESP),
.BVALID(BVALID),
.BREADY(BREADY),
//初始化完成信号
.init_calib_complete(init_calib_complete)  );mig2axi4 U2(
//AXI4接口
//全局信号
.ACLK(ACLK),
.ARESETn(ARESETn),
//读地址通道
.ARADDR(ARADDR),
.ARLEN(ARLEN),
.ARSIZE(),               //2^7=128
.ARBURST(),
.ARPROT(),
.ARVALID(ARVALID),
.ARREADY(ARREADY),
//读数据通道
.RVALID(RVALID),
.RDATA(RDATA),
.RRESP(RRESP),
.RLAST(RLAST),
.RREADY(RREADY),
//写地址通道                 
.AWADDR(AWADDR),
.AWLEN(AWLEN),
.AWSIZE(),
.AWBURST(),
.AWPROT(),            
.AWVALID(AWVALID),
.AWREADY(AWREADY),
//写数据通道
.WDATA(WDATA),
.WSTRB(WSTRB),
.WLAST(WLAST),
.WVALID(WVALID),
.WREADY(WREADY),
//写应答通道
.BRESP(BRESP),
.BVALID(BVALID),
.BREADY(BREADY),
//MIG侧接口        
.ui_clk(ui_clk),                
.ui_clk_sync_rst(ui_clk_sync_rst),       
.init_calib_complete(init_calib_complete),   
.app_rdy(app_rdy),               
.app_wdf_rdy(app_wdf_rdy),           
.app_rd_data_valid(app_rd_data_valid),     
.app_rd_data(app_rd_data),           
.app_addr(app_addr),                                 
.app_en(app_en),                
.app_wdf_wren(app_wdf_wren),          
.app_wdf_end(app_wdf_end),           
.app_cmd(app_cmd),               //3'b000为写数据,3'b001为读数据           
.app_wdf_data(app_wdf_data));mig_7series_0 u_mig_7series_0 (// Memory interface ports.ddr3_addr                      (ddr3_addr),   // output [14: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), // 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 [28: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                  (app_sr_active),// output	    app_sr_active.app_ref_ack                    (app_ref_ack),  // output	    app_ref_ack.app_zq_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                   (31'b0),        // input [31:0]	app_wdf_mask// System Clock Ports.sys_clk_i                      (clk_200),// Reference Clock Ports.clk_ref_i                      (clk_200),.sys_rst                        (sys_rst_n)     // input         sys_rst);//PLLģ�� 
clk_wiz_0 u_clk_wiz_0(// Clock out ports.clk_out1(clk_200),     // output clk_out1// Status and control signals.reset(1'b0),           // input resetn.locked(locked),        // output locked// Clock in ports.clk_in1(sys_clk));        endmodule

测试平台文件编写如下,只需例化top模块和ddr3仿真模型模块即可:
test_tb.sv

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/12/29 20:23:18
// Design Name: 
// Module Name: test_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module test_tb();
parameter T=20;//
logic led;
logic sys_clk;
logic sys_rst_n;
//
wire   [13:0]		ddr3_addr;wire   [2:0]		ddr3_ba;wire  			ddr3_cas_n;wire   [0:0]		ddr3_ck_n;wire   [0:0]		ddr3_ck_p;wire   [0:0]		ddr3_cke;wire  			ddr3_ras_n;wire  			ddr3_reset_n;wire  			ddr3_we_n;wire  [15:0]		ddr3_dq;wire  [1:0]		ddr3_dqs_n;wire  [1:0]		ddr3_dqs_p;wire   [0:0]		ddr3_cs_n;wire   [1:0]		ddr3_dm;wire   [0:0]		ddr3_odt;
//sys_clk
initial beginsys_clk=0;forever begin#(T/2) sys_clk=~sys_clk;end
end
//sys_rst_n
initial beginsys_rst_n=0;#(10*T)sys_rst_n=1; 
end//
// ddr3_rw_top U(
//    .sys_clk(sys_clk),         //
//    .sys_rst_n(sys_rst_n),       //
//     // DDR3
//    .ddr3_dq(ddr3_dq),         //
//    .ddr3_dqs_n(ddr3_dqs_n),      //
//    .ddr3_dqs_p(ddr3_dqs_p),      //   
//    .ddr3_addr(ddr3_addr),       //
//    .ddr3_ba(ddr3_ba),         //
//    .ddr3_ras_n(ddr3_ras_n),      //
//    .ddr3_cas_n(ddr3_cas_n),      //
//    .ddr3_we_n(ddr3_we_n),       //
//    .ddr3_reset_n(ddr3_reset_n),    //
//    .ddr3_ck_p(ddr3_ck_p),       //
//    .ddr3_ck_n(ddr3_ck_n),       //
//    .ddr3_cke(ddr3_cke),        //
//    .ddr3_cs_n(ddr3_cs_n),       //
//    .ddr3_dm(ddr3_dm),         //
//    .ddr3_odt(ddr3_odt),        //
//    .led(led)              //
//     ); 
top U(
.sys_clk(sys_clk),         //ϵͳʱ��
.sys_rst_n(sys_rst_n),       //��λ,����Ч
// DDR3
.ddr3_dq(ddr3_dq),         //DDR3 ����
.ddr3_dqs_n(ddr3_dqs_n),      //DDR3 dqs��
.ddr3_dqs_p(ddr3_dqs_p),      //DDR3 dqs��       
.ddr3_addr(ddr3_addr),       //DDR3 ��ַ
.ddr3_ba(ddr3_ba),         //DDR3 banck ѡ��
.ddr3_ras_n(ddr3_ras_n),      //DDR3 ��ѡ��
.ddr3_cas_n(ddr3_cas_n),      //DDR3 ��ѡ��
.ddr3_we_n(ddr3_we_n),       //DDR3 ��дѡ��
.ddr3_reset_n(ddr3_reset_n),    //DDR3 ��λ
.ddr3_ck_p(ddr3_ck_p),       //DDR3 ʱ����
.ddr3_ck_n(ddr3_ck_n),       //DDR3 ʱ�Ӹ�
.ddr3_cke(ddr3_cke),        //DDR3 ʱ��ʹ��
.ddr3_cs_n(ddr3_cs_n),       //DDR3 Ƭѡ
.ddr3_dm(ddr3_dm),         //DDR3_dm
.ddr3_odt(ddr3_odt)         //DDR3_odt
);ddr3_model V
(.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),.ba      (ddr3_ba),.addr    (ddr3_addr),.dq      (ddr3_dq),.dqs     (ddr3_dqs_p),.dqs_n   (ddr3_dqs_n),.tdqs_n  (),.odt     (ddr3_odt));endmodule

下图是整个工程的RTL视图,它很好的揭示了上述代码之间的关系:
在这里插入图片描述

结果分析

AXI4写数据波形图

在这里插入图片描述

可以看到,当app_rdy、app_wdf_rdy(表明ddr已经准备好接收数据)以及WVALID信号(表示要写的数据已经有效)同时为高时,app_en、app_wdf_wren、WREADY信号均被拉高,开始写入一个数据。

AXI4读数据波形图

写命令

在这里插入图片描述
如图所示,app_cmd为3’b001,app_en,app_rdy均为高,表示该读命令已被接受,而app_addr为要读的数据的地址。

读数据

在这里插入图片描述
如图所示,MIG将读取的数据先存入缓存中,然后再将缓存中的数据通过AXI4的读数据通道发送给主机。(通过使用FIFO可以进一步增大读数据的效率)


http://www.ppmy.cn/news/560858.html

相关文章

vivado生成mig_Xilinx-在Zynq上用MIG扩展内存(2)-Vivado篇

硬件平台:ZC706开发板 软件工具:Vivado 2013.2 Step 1: 创建工程 启动Vivado 2013.2,创建一个新的工程zc706_mig。选中Create project subdirectory。 选择RTL Project 一路Next,在Default Part页面选择ZC706开发板。 Step 2: 配置Zynq 在左面的Flow Navigator窗口,单击Cre…

DDR3 控制器 MIG IP 详解完整版 (VIVADOVerilog)

文章目录 前言一、DDR 控制器 IP 创建流程1、搜索查找 DDR 控制器 IP。2、MIG IP 的配置。 二、DDR 控制器 AXI 接口协议简介1.IP例化模板2.IP例化接口&#xff08;1&#xff09; 写地址通道信号&#xff08;2&#xff09; 写数据通道信号&#xff08;3&#xff09; 写响应通道…

读故事学BEC英语单词(一)

故事 In a bustling city, there lived a determined young entrepreneur named Emily. She had always been passionate about creating innovative solutions to everyday problems. One day, she came up with an ingenious idea for a new app that would revolutionize t…

XIlinx MIG 控制DDR3 SO-DIMM内存条(二):MIG IP核学习

目录 1 简介2 IP核自定义2.1 设置IP核参数2.1.1 Pin Compatible FPGAs2.1.2 Memory Selection2.1.3 Controller Options2.1.4 AXI Parameter2.1.5 Memory Options2.1.6 FPGA Options2.1.7 Extended FPGA Options2.1.8 IO Planning Options2.1.9 Pin Selection2.1.10 System Sig…

【Nvidia】nvidia 高级特性MIG详细介绍(三)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

vfifo控制mig_基于MIG IP核的DDR3控制器(一)

最近学习了DDR3控制器的使用,也用着DDR完成了一些简单工作,想着以后一段可能只用封装过后的IP核,可能会忘记DDR3控制器的一些内容,想着把这个DDR控制器的编写过程记录下来,便于我自己以后查看吧,哈哈哈,闲话少说开始工作。这个DDR3控制器分两节内容吧,第一节就是MIGIP核…

vfifo控制mig_浅析Xilinx家DDR控制器MIG的使用

FPGA的片上存储资源bram简单好用,时序清晰,要不是总容量往往就几十Mb谁愿意用DDR呀 害,言归正传,因为设计需要存储1477x1800x3 双精度浮点复数这样的大号矩阵,所以只能放到DDR上去进行读写。之前在网上找了好多资料,但发现都没有一个很完整的教程教你怎么使用DDR控制器IP…

vivado生成mig_Vivado下MIG核仿真指导手册 -

4) sim/sim_tb_top.v: 在实例化ddr3_model模块部分,增加了实例化参数的赋值,参照“仿 真文件改动”目录下的sim_tb_top_modified_part.v的内容作对应的修改即可。 说明:example_top.v和sim_tb_top.v中,涉及到MIG核的所有配置参数,因此在源文件中 修改对应的部分;ddr3_mod…