当前位置:   article > 正文

DDR3 MIG IP 核 NATIVE接口 仿真_ddr3 用户接口仿真

ddr3 用户接口仿真

官方例程仿真

建立官方示例

继上文建立mig ip核后,右键点击生成的IP核,然后选择open ip example design
在这里插入图片描述
然后会自动生成一个新工程,点击run simulation直接进行仿真即可,对波形进行分类如下:

波形分析

写指令

在这里插入图片描述
由上图可以看出,当app_cmd[2:0] == 3'd0时,进入写状态。在写状态,只有当app_en == 1 && app_rdy == 1时,app_addr 才会递增,这里突发长度是8。
在这里插入图片描述

写数据

在写状态时,app_wdf_wrenapp_wdf_rdy必须同时拉高,才可以写进数据。否则数据保持前一个状态不变。
在这里插入图片描述

读数据

在这里插入图片描述
由上图可以看出,只要app_rd_data_valid拉高,app_rd_data就会变化,即数据可以被读出。当app_rd_data_valid拉低时,读出的数据保持之前状态的数据。在此期间,写数据保持不变。
在这里插入图片描述
在这里插入图片描述

自己编写代码进行仿真

这里是先写入512个数,然后读出512个数,采用写命令与写数据发生在同一时钟周期的模式,比较简单。仿真需要注意:
1.在自己进行仿真时,需要添加官方例程里面的两个文件到自己的工程里,下图所示的ddr3_model_parameter.vh以及sim_tb_top里的ddr3_model(ddr3_model.sv)
在这里插入图片描述
在这里插入图片描述
2.仿真时长最好设置为120us,不然可能等不到init_calib_complete拉高。
3.ui模块的复位是高电平有效,其他都是低电平。
4.app_sr_req,app_ref_req,app_zq_req 需设置为低电平。

代码如下

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/12 19:44:49
// Design Name: 
// Module Name: ddr3_rw
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 写进去512个数,读出来512个数
// 采用写命令与写数据发生在同一时钟周期的模式
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module ddr3_rw(
    input   wire          ui_clk                ,
    input   wire          ui_clk_sync_rst       ,
    input   wire          init_calib_complete   ,

    input   wire          app_rdy               ,
    input   wire[127:0]   app_rd_data           ,
    input   wire          app_rd_data_end       ,
    input   wire          app_rd_data_valid     ,
    input   wire          app_wdf_rdy           ,

    output  reg[27:0]     app_addr              ,//ddr3地址-512个数
    output  wire[2:0]     app_cmd               ,
    output  wire          app_en                ,
    output  reg[127:0]    app_wdf_data          ,
    output  wire          app_wdf_end           ,
    output  wire          app_wdf_wren          
    );
//parameter define
parameter  DATA_LENGTH =    512;
localparam IDLE        =    4'b0001;
localparam WRITE       =    4'b0010;
localparam WAIT        =    4'b0100; 
localparam READ        =    4'b1000;

//wire define 
wire sys_rst_n;

//reg define
reg[3:0]      cur_state;
reg[3:0]      next_state;
reg[24:0]     rd_addr_cnt;//用户读地址计数
reg[24:0]     wr_addr_cnt;//用户写地址计数
reg[24:0]     rd_cnt;//实际读地址计数
//main code
assign sys_rst_n = ~ui_clk_sync_rst;
assign app_cmd = (cur_state == READ) ? 1 :0;
assign app_en = (cur_state == WRITE && app_rdy && app_wdf_rdy) || (cur_state == READ && app_rdy);//写状态时读写数据和写命令都准备好,读状态时,读命令准备好
assign app_wdf_wren = (cur_state == WRITE) && app_rdy && app_wdf_rdy;
assign app_wdf_end = app_wdf_wren;//ddr3芯片和用户时钟分频是4:1,突发长度是8,因此两个信号相等
//fsm
always @(posedge ui_clk or negedge sys_rst_n) begin
    if(~sys_rst_n) begin
        cur_state <= IDLE;
    end else 
        cur_state <= next_state;
end

always @(*)begin
    if(~sys_rst_n) 
        next_state <= IDLE;
    else if(init_calib_complete == 1)
        case(cur_state)
            IDLE:
                next_state <= WRITE;
            WRITE:
                if(wr_addr_cnt == DATA_LENGTH - 1 && app_rdy == 1 && app_wdf_rdy == 1)
                    next_state <= WAIT;
                else
                    next_state <= WRITE;
            WAIT:
                next_state <= READ;
            READ:
                if(rd_addr_cnt == DATA_LENGTH - 1 && app_rdy == 1 )
                    next_state <= IDLE;
                else
                    next_state <= READ;
            default: next_state <= IDLE;
        endcase
end

always @(posedge ui_clk or negedge sys_rst_n) begin
    if(~sys_rst_n) begin
        app_addr <= 'd0;
        app_wdf_data <= 'd0;
        wr_addr_cnt <= 'd0;
        rd_addr_cnt <= 'd0;
    end
    else begin
        case(cur_state)
            IDLE:begin
                app_addr <= 'd0;
                app_wdf_data <= 'd0;
                wr_addr_cnt <= 'd0;
                rd_addr_cnt <= 'd0;
            end
            WRITE:begin
                if(app_rdy && app_wdf_rdy) begin
                    app_addr     <= app_addr + 'd8;
                    app_wdf_data <= app_wdf_data + 1'b1;
                    wr_addr_cnt  <= wr_addr_cnt + 1'b1;
                    rd_addr_cnt  <= 'd0;
                end else begin
                    app_addr     <=  app_addr     ;
                    app_wdf_data <=  app_wdf_data ;
                    wr_addr_cnt  <=  wr_addr_cnt  ;
                    rd_addr_cnt  <=  'd0  ; 
                end
            end
            WAIT:begin
                app_addr        <= 'd0;
                app_wdf_data    <= app_wdf_data ;
                wr_addr_cnt     <= wr_addr_cnt  ;
                rd_addr_cnt     <= rd_addr_cnt  ;
            end
            READ:begin
                if(app_rdy) begin//读数据只要读命令有效就会读数据,只有app_rd_data_valid拉高时才表示读出的数据有效
                    app_addr <= app_addr + 'd8;
                    rd_addr_cnt <= rd_addr_cnt + 1'b1;
                end else begin
                    app_addr        <= app_addr     ;
                    rd_addr_cnt     <= rd_addr_cnt  ;
                end
            end
            default:begin
                app_addr <= 'd0;
                rd_addr_cnt <= 'd0;
            end

        endcase
    end
end

always @(posedge ui_clk or negedge sys_rst_n) begin
    if(sys_rst_n == 1'b0) begin
        rd_cnt <= 'd0;
    end else if(app_rd_data_valid == 1 && rd_cnt == DATA_LENGTH - 1) begin
        rd_cnt <= 'd0;
    end else if (app_rd_data_valid) begin
        rd_cnt <= rd_cnt + 1'b1;
    end
end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/13 17:02:45
// Design Name: 
// Module Name: ddr3_rw_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module ddr3_rw_top(
    input   wire          sys_clk            ,
    input   wire          sys_rst_n          , 
    input   wire[15:0]     ddr3_dq            ,//input,DDR3数据
    input   wire[1:0]      ddr3_dqs_n         ,//input,dqs负
    input   wire[1:0]      ddr3_dqs_p         ,//input,dqs正

    output  wire[13:0]     ddr3_addr          ,
    output  wire[2:0]      ddr3_ba            ,
    output  wire           ddr3_ras_n         ,
    output  wire           ddr3_cas_n         ,
    output  wire           ddr3_we_n          ,
    output  wire           ddr3_reset_n       ,
    output  wire[0:0]      ddr3_ck_p          ,
    output  wire[0:0]      ddr3_ck_n          ,
    output  wire[0:0]      ddr3_cke           ,
    output  wire[0:0]      ddr3_cs_n          ,
    output  wire[1:0]      ddr3_dm             ,
    output  wire[0:0]      ddr3_odt           
    );

    wire         ui_clk;
    wire         ui_clk_sync_rst;
    wire         init_calib_complete;
    
    wire         app_rdy;    
    wire[127:0]  app_rd_data;
    wire         app_rd_data_end  ;
    wire         app_rd_data_valid;
    wire         app_wdf_rdy      ;
    wire[27:0]   app_addr   ;
    wire[2:0]    app_cmd     ;
    wire         app_en           ;
    wire[127:0]  app_wdf_data;
    wire         app_wdf_end      ;
    wire         app_wdf_wren     ;

    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[11:0]   device_temp  ;
    wire         sys_rst      ;

    ddr3_rw inst0(
            .ui_clk              (ui_clk              ),
            .ui_clk_sync_rst     (ui_clk_sync_rst     ),
            .init_calib_complete (init_calib_complete ),
            .app_rdy             (app_rdy             ),
            .app_rd_data         (app_rd_data         ),
            .app_rd_data_end     (app_rd_data_end     ),
            .app_rd_data_valid   (app_rd_data_valid   ),
            .app_wdf_rdy         (app_wdf_rdy         ),
            .app_addr            (app_addr            ),
            .app_cmd             (app_cmd             ),
            .app_en              (app_en              ),
            .app_wdf_data        (app_wdf_data        ),
            .app_wdf_end         (app_wdf_end         ),
            .app_wdf_wren        (app_wdf_wren        )
    );
    mig_7series_0 inst1(
        .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      ),     

        .sys_clk_i                  (clk_200M),    
        .clk_ref_i                  (clk_200M),     

        .app_addr                   (app_addr            ),      
        .app_cmd                    (app_cmd             ),     
        .app_en                     (app_en              ),     
        .app_wdf_data               (app_wdf_data        ),      
        .app_wdf_end                (app_wdf_end         ),     
        .app_wdf_mask               (32'b0               ), //need to revise   
        .app_wdf_wren               (app_wdf_wren        ),     
        .app_rd_data                (app_rd_data         ),     
        .app_rd_data_end            (app_rd_data_end     ),     
        .app_rd_data_valid          (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, no need parameter      
        .app_ref_req                (1'b0),//input, no need parameter    
        .app_zq_req                 (1'b0),//input, no need parameter     
        .app_sr_active              (app_sr_active),//output,remain no change    
        .app_ref_ack                (app_ref_ack),//output,remain no change
        .app_zq_ack                 (app_zq_ack),//output,remain no change
        .ui_clk                     (ui_clk),
        .ui_clk_sync_rst            (ui_clk_sync_rst),
        .init_calib_complete        (init_calib_complete ),
        .device_temp                (device_temp),//output,remain no change
        .sys_rst                    (sys_rst_n)
      
    );
    clk_wiz_0 inst2
    (
    // Clock out ports  
    .clk_out1                       (clk_200M       ),
    // Status and control signals               
    .resetn                         (sys_rst_n      ), 
    .locked                         (locked         ),
   // Clock in ports 
    .clk_in1                        (sys_clk        )
    );
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/13 20:06:50
// Design Name: 
// Module Name: tb_ddr3_rw_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module tb_ddr3_rw_top();

reg             sys_clk     ;
reg             sys_rst_n   ;

wire[15:0]      ddr3_dq     ;
wire[1:0]       ddr3_dqs_n  ;
wire[1:0]       ddr3_dqs_p  ;
wire[13:0]      ddr3_addr   ;
wire[2:0]       ddr3_ba     ;
wire            ddr3_ras_n  ;
wire            ddr3_cas_n  ;
wire            ddr3_we_n   ;
wire            ddr3_reset_n;
wire            ddr3_ck_p   ;
wire            ddr3_ck_n   ;
wire            ddr3_cke    ;
wire            ddr3_cs_n   ;
wire[1:0]       ddr3_dm      ;
wire            ddr3_odt    ;

initial begin
    sys_clk <= 1'b0;
    sys_rst_n <= 1'b0;
    #20
    sys_rst_n <= 1'b1;
end

always #10 sys_clk <= ~sys_clk;

ddr3_rw_top uu(
    .sys_clk     (sys_clk     ),
    .sys_rst_n   (sys_rst_n   ),
    .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    )
);

ddr3_model uu0(
    .rst_n       (sys_rst_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    )
);

//ddr3_model uu0(
//    .rst_n       (sys_rst_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[1:0]),
//    .ba          (ddr3_ba     ),
//    .addr        (ddr3_addr   ),
//    .dq          (ddr3_dq[15:0]),
//    .dqs         (ddr3_dqs_p[1:0]),
//    .dqs_n       (ddr3_dqs_n[1:0]),
//    .tdqs_n      (     ),
//    .odt         (ddr3_odt    )
//);
//ddr3_model uu1(
//    .rst_n       (sys_rst_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[3:2]      ),
//    .ba          (ddr3_ba     ),
//    .addr        (ddr3_addr   ),
//    .dq          (ddr3_dq[31:16]     ),
//    .dqs         (ddr3_dqs_p[3:2]  ),
//    .dqs_n       (ddr3_dqs_n[3:2]  ),
//    .tdqs_n      (     ),
//    .odt         (ddr3_odt    )
//);
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126

仿真波形

在这里插入图片描述

写命令

在这里插入图片描述

写数据

在这里插入图片描述
在这里插入图片描述
可以看出写了512个数后清零,地址增长到4096后清零,是正确的

读数据

在这里插入图片描述
可以看到写入读命令一段时间以后,数据才会被读出,读到512个数后停止读。

复盘

1.本次实验的mig ip核的数据位宽设置的是16位,因此在例化ddr3_model时只例化了一个(ddr3_model也是16位),如果自己在设置时是16的倍数(32,64等),那么在例化时也需要例化多个ddr3_model
2.在写代码时有错误导致写数据正常,但读不出数据。
在这里插入图片描述
上图是错误的,下图是正确的。
在这里插入图片描述

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号