【FPGA】MIG DDR3读写逻辑测试

这篇具有很好参考价值的文章主要介绍了【FPGA】MIG DDR3读写逻辑测试。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

        笔者在之前通过microblaze软核的方式实现了DDR3芯片的读写测试,当时对于Xilinx MIG DDR控制器的理解还比较肤浅。还是想通过控制用户接口时序的方式来读写DDR,扩展和加深自己对DDR的理解。

MIG IP核配置请看我的前一篇文章

【FPGA测试】Microblaze测试DDR读写_microblaze ddr-CSDN博客

里面关于MIG参考时钟输入有错误的地方,这里改正一下。

ddr3测试方法,fpga开发

MIG的输入时钟有2种,一个是系统时钟,如下图所示,input Clock period。还有一个时钟为参考时钟,固定为200MHz。

ddr3测试方法,fpga开发

DDR读写时序

首先是命令,如图,只有当app_rdy信号为高时,用户给MIG的指令才有效。

ddr3测试方法,fpga开发

然后是写指令,一种是写数据和写命令同时进行。第二种是写的数据慢于写命令。第三种是写的数据快于写指令。一般来说采用同时写数据和写命令即可。

ddr3测试方法,fpga开发

        当输入读命令和读地址时,延迟几个时钟周期后,开始读出数据。当app_rd_data_vaild为高时,读出的数据才是正确且有效的。

ddr3测试方法,fpga开发

测试代码如下:

每给一个地址,会往ddr里写8个32bit的数据。这样一次写命令就可以写满8个地址。

所以每写一次,地址都要加8。

同时。每读一次,会读出8个地址的数据,所以每次读一次,地址也要加8。

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/23 14:03:36
// Design Name: 
// Module Name: DDR3
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module DDR3(
    ddr3_addr,
    ddr3_ba,
    ddr3_cas_n,
    ddr3_ck_n,
    ddr3_ck_p,
    ddr3_cke,
    ddr3_cs_n,
    ddr3_dm,
    ddr3_dq,
    ddr3_dqs_n,
    ddr3_dqs_p,
    ddr3_odt,
    ddr3_ras_n,
    ddr3_reset_n,
    ddr3_we_n,
    
    clk_100M,
    rst_n
    );
	
  output [14:0]ddr3_addr;
  output [2:0]ddr3_ba;
  output ddr3_cas_n;
  output [0:0]ddr3_ck_n;
  output [0:0]ddr3_ck_p;
  output [0:0]ddr3_cke;
  output [0:0]ddr3_cs_n;
  output [3:0]ddr3_dm;
  inout [31:0]ddr3_dq;
  inout [3:0]ddr3_dqs_n;
  inout [3:0]ddr3_dqs_p;
  output [0:0]ddr3_odt;
  output ddr3_ras_n;
  output ddr3_reset_n;
  output ddr3_we_n;
  
  input clk_100M;
  input rst_n;
  
  wire [14: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 [0:0]ddr3_cs_n;
  wire [3:0]ddr3_dm;
  wire [31:0]ddr3_dq;
  wire [3:0]ddr3_dqs_n;
  wire [3:0]ddr3_dqs_p;
  wire [0:0]ddr3_odt;
  wire ddr3_ras_n;
  wire ddr3_reset_n;
  wire ddr3_we_n;

  wire clk_100M;
  wire rst_n;
  
  wire init_calib_complete; 
  wire [28: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 app_sr_req;
  wire app_ref_req;
  wire app_zq_req;
  wire app_sr_active;
  wire app_ref_ack;
  wire app_zq_ack;
  wire ui_clk;
  wire ui_clk_sync_rst;
  wire [31:0] app_wdf_mask;
  wire sys_clk_i;
  wire clk_ref_i;
  wire sys_rst;
  
  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),  // 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 [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                     (app_sr_req),  // input			app_sr_req
    .app_ref_req                    (app_ref_req),  // input			app_ref_req
    .app_zq_req                     (app_zq_req),  // 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                   (app_wdf_mask),  // input [31:0]		app_wdf_mask
    // System Clock Ports
    .sys_clk_i                       (sys_clk_i),
    // Reference Clock Ports
    .clk_ref_i                      (clk_ref_i),
    .sys_rst                        (sys_rst) // input sys_rst

    );
 
 wire clk_200M;
 wire rst;
 wire locked;
   clk_wiz_0 instance_name
   (
    // Clock out ports
    .clk_out1(clk_200M),     // output clk_out1
    // Status and control signals
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(clk_100M));  
 
 assign sys_clk_i = clk_200M;
 assign clk_ref_i = clk_200M;
 assign rst = rst_n;
 assign sys_rst = rst_n;
 
 parameter    [2:0]IDLE  =3'd0;
 parameter    [2:0]WRITE =3'd1;
 parameter    [2:0]CLC=3'd2;
 parameter    [2:0]WAIT  =3'd3;
 parameter    [2:0]READ  =3'd4;
 parameter    [2:0]CMD_WRITE    =3'd0;
 parameter    [2:0]CMD_READ     =3'd1;
 parameter    TEST_DATA_RANGE   =28'd1000;//测试1000个地址

 reg   [2 :0]state=0;
 reg    [31:0]Count_64; 
 reg    [27:0]app_addr_begin; 
 
 assign    app_wdf_end                     =app_wdf_wren;
 assign    app_en                          =(state==WRITE) ? (app_rdy&&app_wdf_rdy) : ((state==READ)&&app_rdy);
 assign    app_wdf_wren                    =(state==WRITE) ? (app_rdy&&app_wdf_rdy) : 1'b0;
 assign    app_cmd                         =(state==WRITE) ? CMD_WRITE : CMD_READ;
 assign    app_addr                        =app_addr_begin;
 assign    app_wdf_data                    ={
                                                Count_64[31:0],(Count_64[31:0]+32'd1),(Count_64[31:0]+32'd2),(Count_64[31:0]+32'd3),
                                                (Count_64[31:0]+32'd4),(Count_64[31:0]+32'd5),(Count_64[31:0]+32'd6),(Count_64[31:0]+32'd7)
                                             };//一次写入8个地址


always@(posedge clk_100M)
    if(!rst&!init_calib_complete)
        begin
        state                           <=IDLE;
        app_addr_begin                  <=28'd0;
        Count_64                       <=32'd0;
        end
 else case(state)
     IDLE:    begin
        state                            <=WRITE;
        if(app_addr_begin >= TEST_DATA_RANGE)
        app_addr_begin                 <=28'd0;
        Count_64                         <=32'd0;
        end
     WRITE:    begin
        state                            <=(Count_64>=TEST_DATA_RANGE)&&app_rdy&&app_wdf_rdy ? CLC:state;
        Count_64                         <=app_rdy&&app_wdf_rdy?(Count_64+32'd8):Count_64;    
        app_addr_begin                   <=app_rdy&&app_wdf_rdy?(app_addr_begin+28'd8):app_addr_begin;8*32=256
        end
     CLC:    begin
        state                            <=WAIT;
        Count_64                         <=32'd0;    
        app_addr_begin                   <=28'd0;    
        end
     WAIT:    begin
        state                            <=READ;
        Count_64                         <=32'd0;    
        app_addr_begin                   <=28'd0;    
        end     
     READ:    begin
        state                            <=(Count_64>=TEST_DATA_RANGE)&&app_rdy? IDLE:state;
        Count_64                         <=app_rdy?(Count_64+32'd8):Count_64;    
        app_addr_begin                   <=app_rdy?(app_addr_begin+28'd8):app_addr_begin;
        end
 default:begin
        state                            <=IDLE;
        app_addr_begin                   <=28'd0;
        Count_64                         <=32'd0;
        end        
    endcase
 
reg [27:0] count;

always@(posedge clk_100M)
    if(!rst)
       count <= 28'b0;
    else if(app_rd_data_valid)begin
        if(app_rd_data[255:224]==32'd0)
          count <= 28'd8;
        else  
          count <= count + 28'd8;
    end
    else if(count >= 28'd1000)   
       count <= 28'b0;  
       
 
 ila_0 u1 (
	.clk(clk_100M), // input wire clk
	.probe0(app_cmd), // input wire [2:0]  probe0  
	.probe1(state), // input wire [1:0]  probe1 
	.probe2(Count_64), // input wire [23:0]  probe2 
	.probe3(app_addr_begin), // input wire [27:0]  probe3 
	.probe4(app_rd_data), // input wire [255:0]  probe4 
	.probe10(app_rd_data_valid), // input wire [0:0]  probe5 
	.probe6(app_en), // input wire [0:0]  probe6 
	.probe7(app_wdf_wren), // input wire [0:0]  probe7 
	.probe8(app_rdy), // input wire [0:0]  probe8 
	.probe9(app_wdf_rdy), // input wire [0:0]  probe9 
    .probe5(app_wdf_data),
    .probe11(app_rd_data[31:0]),
    .probe12(app_rd_data[255:224]),
    .probe13(count),
    .probe14(app_rd_data_valid)
);
endmodule

首先看一下写的情况,从零地址开始,每个地址写上地址数,共写1000个地址。

ddr3测试方法,fpga开发

ddr3测试方法,fpga开发

再看一下读的情况,每次读出8个地址的32位数据。

ddr3测试方法,fpga开发

如上图所示,黄线处开始读命令,但是此时并没有有效数据读出,需要等待几个时钟周期,才能读出正确数据。

ddr3测试方法,fpga开发

如上图所示,读出的数据是正确的。文章来源地址https://www.toymoban.com/news/detail-815325.html

到了这里,关于【FPGA】MIG DDR3读写逻辑测试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA入门 —— DDR3(MIG IP 核) 入门

    DDR 简介 DDR=Double Data Rate双倍速率同步动态随机存储器。严格的说DDR应该叫DDR SDRAM,人们习惯称为DDR,其中,SDRAM 是Synchronous Dynamic Random Access Memory的缩写,即同步动态随机存取存储器。而DDR SDRAM是Double Data Rate SDRAM的缩写,是双倍速率同步动态随机存储器的意思。 SDRAM在一个时

    2024年01月16日
    浏览(43)
  • 【Xilinx FPGA】DDR3 MIG 时钟管脚分配

    之前在验证 FPGA 板卡的芯片管脚时,所用的测试工程使用内部 PLL 生成的时钟作为 DDR3 的参考时钟。后来尝试将参考时钟改为外部 100M 晶振时钟,发现 MIG IP 配置工具找不到相应管脚,于是学习并梳理了 Xilinx DDR3 MIG IP 时钟管脚的分配规则,在这里做个记录。   目录 1 MIG 时钟

    2024年02月06日
    浏览(35)
  • DDR3(MIG核配置&官方demo&FPGA代码实现及仿真)

      由于直接对 DDR3 进行控制很复杂,因此一般使用 MIG IP 来实现,同时为了更简单地使用 MIG IP,我们采用 AXI4 总线协议进行控制。下面首先介绍 MIG IP 的配置,然后看看官方 demo (里面包含一个仿真要用到的 DDR3 模型)及其仿真结果,最后进行我们自己的控制代码实现。  

    2024年02月05日
    浏览(32)
  • 【FPGA】十三、Vivado MIG IP核实现DDR3控制器(1)

    文章目录 前言 一、DDR3基础知识 二、MIG  IP核的配置 三、DDR3 IP核用户端接口时序 1、DDR3 IP核接口说明 2、DDR3 IP核读写时序 ① 写命令时序:  ② 写数据时序:  ③ 读数据时序: 总结         我们在进行FPGA开发应用当中,经常会用到存储器来保存数据,常用的存储器有RO

    2024年02月16日
    浏览(65)
  • 超详细的FPGA使用MIG调用SODIMM DDR3内存条接口教程

    SODIMM 接口DDR3适配额外的内存条才能满足数据缓存的需求,这种需求一般用于高端项目,DDR3 SDRAM 常简称 DDR3, 是当今较为常见的一种储存器, 在计算机及嵌入式产品中得到广泛应用,特别是应用在涉及到大量数据交互的场合。 本文以XC7K325T-FFG900-2L为例,记录MIG的配置过程,

    2024年02月02日
    浏览(36)
  • 基于紫光同创 FPGA 的 DDR3 读写实验

    此篇为专栏 《紫光同创FPGA开发笔记》 的第二篇,记录我的学习FPGA的一些开发过程和心得感悟,刚接触FPGA的朋友们可以先去此专栏置顶 《FPGA零基础入门学习路线》来做最基础的扫盲。 本篇内容基于笔者实际开发过程和正点原子资料撰写,将会详细讲解此 FPGA 实验的全流程

    2024年01月20日
    浏览(42)
  • FPGA-基于AXI4接口的DDR3读写顶层模块

    AXI4(Advancede Xtensible Interface 4)是一种高性能、高带宽的总线接口协议,用于在系统级芯片设计中连接不同的IP核(Intellectual Property)或模块。它是由ARM公司开发的,被广泛应用于各种SoC(System-on-Chip)设计中。 AXI4接口协议定义了一组规范,用于描述数据传输、地址传输、控

    2024年04月15日
    浏览(42)
  • 【两周学会FPGA】从0到1学习紫光同创FPGA开发|盘古PGL22G开发板学习之DDR3 IP简单读写测试(六)

    本原创教程由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 适用于板卡型号: 紫光同创PGL22G开发平台(盘古22K) 一:盘古22K开发板(紫光同创PGL22G开发平台)简介 盘古22K开发板是基于紫光同创Logos系列PGL22G芯片设计的一款FPGA开发板,全

    2024年01月23日
    浏览(55)
  • 基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制

    基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制,模块接口清晰,可移植性高. 基于FPGA的DDR3读写控制是一项重要的技术,它为多通道图像数据的读写提供了高效的解决方案。本文将介绍一种纯Verilog实现的DDR3读写控制模块,旨在实现模块接口清晰、可移

    2024年04月12日
    浏览(48)
  • 到中流击水—XILINX (MIG) DDR3 UI接口

    1.DDR3内核时钟:DDR3内部逻辑部分使用的时钟,用户侧无需关心,跟DDR3芯片内核性能相关。 2.DDR3接口时钟:DDR3与外界通信实际使用的时钟(实际时钟),跟DDR3芯片接口性能相关。 3.DDR3等效时钟:DDR3与外界通信实际的有效时钟(双倍速率)。 1.FPGA参考时钟:FPGA用于MIG IP数据

    2024年02月06日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包