Menu Close

DDR3 控制器Verilog测试程序

1. 工程代码下载:

FPGA_DDR3_IO

2. 利用Mark_debug 抓取的波形如下:

%title插图%num

图1 写波形

%title插图%num

图2 读波形

3.  测试源程序

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2020/05/12 17:45:17
// Design Name: 
// Module Name: ddr_rd_wrrd_wr
// Project Name: ddr3_intf
// Target Devices: Artix 7 100T
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// clock ratio 4:1  
// DDR clock frequency 400Mhz
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module ddr_rd_wr(
   // input  [127:0]     data_in,
    (* MARK_DEBUG="true" *)  output reg [26:0]	app_addr                , 
     (* MARK_DEBUG="true" *) output reg [2:0]   app_cmd                 , 
    (* MARK_DEBUG="true" *)  output reg		app_en                  , 
    (* MARK_DEBUG="true" *)  input		app_rdy                 ,
    
    (* MARK_DEBUG="true" *)  output reg [127:0]	app_wdf_data            , 
                             output reg [15:0]  app_wdf_mask            ,
    (* MARK_DEBUG="true" *)  output 	        app_wdf_end             , 
    (* MARK_DEBUG="true" *)  output reg		app_wdf_wren            , 
    (* MARK_DEBUG="true" *)  input	        app_wdf_rdy             , 
    
     (* MARK_DEBUG="true" *) input [127:0]      app_rd_data             ,
    (* MARK_DEBUG="true" *)  input	        app_rd_data_end         ,
     (* MARK_DEBUG="true" *) input	        app_rd_data_valid       ,
    input			                clk                     ,
    input			                rst_n                   ,
 (* MARK_DEBUG="true" *)    output  reg         error_flag               = 0  ,
 output                             reg         end_flag                 = 0    

    );
 
 parameter    BURST_WR_128BIT = 16777216 ;  //0x100_0000       测试写容量
 parameter    BURST_RD_128BIT = 16777216 ;  //0x100_0000       测试读容量
 parameter    DATA            = 128'habcdef1234567890abcdef1234567890 ;   //测试数据
 

//  Read and write once every 1 second 

 (* MARK_DEBUG="true" *) reg [27:0] scnt = 0    ;  // 分频 ,将100M时钟分频成 周期2秒的方波,高电平和低电平各1秒。

always @  (posedge clk)
if (!rst_n)
    begin 
     scnt     <= 0 ;
     end_flag <= 0 ;
    end 
else if (scnt < 28'd199_999_999)
    begin 
     scnt  <= scnt + 1;
    end_flag <= 0   ;
    end 
else 
    begin 
    scnt <= 0 ;
    end_flag <=  ~end_flag  ;
    end 


 (* MARK_DEBUG="true" *) wire time_wrreq = ( scnt == 28'd100_000_000 ) ;
 (* MARK_DEBUG="true" *) wire time_rdreq  = ( scnt == 28'd000_000_000)  ;

 (* MARK_DEBUG="true" *) reg[1:0] cstate;     //current state     
  reg[1:0] nstate;                            //next state
 (* MARK_DEBUG="true" *) reg [31:0] num = 0 ;  
 (* MARK_DEBUG="true" *) reg [31:0] wrnum = 0 ;


always @ (posedge clk )
if (!rst_n)
     cstate <= 0 ;
    else cstate <=nstate ;

always @(cstate , time_wrreq ,time_rdreq ,num ,app_rdy ,app_wdf_rdy)

case (cstate)

  0  : begin 
         if ( time_wrreq )               //write request
                nstate <= 1 ;
         else  if (time_rdreq ) 
                nstate <= 2 ;
         else   nstate <= 0 ;
       end 

  1:  begin 
        if (( wrnum >= BURST_WR_128BIT) && (num >=BURST_WR_128BIT ) ) 
            nstate <= 3 ; 
        else 
            nstate <= 1 ; 
        end 
  2:  begin 
        if  (num >= BURST_RD_128BIT) 
            nstate <= 3 ;
        else  
            nstate <= 2 ;
      end 
  3:  begin 
        nstate <= 0 ;     
      end 
endcase 


always @ (posedge clk)

    if (!rst_n)
        num <= 32'd0 ;
    else 
        if (cstate ==1) 
            begin 
                if ( app_rdy & app_en )
                    num <= num+ 1 ;
            end             
        else 
            if ( cstate == 2) 
                begin 
                    if (app_rdy & app_en)
                        num <= num +1 ;
                end 
            else num <=  0 ;





always @ ( posedge clk)

if (!rst_n) wrnum <= 32'd0 ;
else 
    if (cstate == 1) 
            begin
                if (app_wdf_rdy & app_wdf_wren) begin
                    wrnum <=  wrnum +1 ;
                    end

            end  
    else wrnum <= 0 ;


////////////////////////////////////////////////////
//地址命令
//reg[27:0] app_addr,	//DDR3地址总线
//reg[2:0] app_cmd,     //DDR3命令总线: 3‘b000--写;3'b001--读;
//reg app_en,	        //地址命令使能,高电平有效

//  读写数据

always@ (posedge clk  )

if (~rst_n)
begin 
    app_cmd <= 3'd0 ;
    app_en  <= 1'b0 ;
    app_addr <=27'd0 ;
end 

else  begin
    if ( cstate == 1)
        begin 
            app_cmd <= 3'b000 ;  //write data to ddr3
             if ( num < BURST_WR_128BIT  ) 
                  app_en   <= 1 ;
             else 
                   app_en   <= 0 ;
                   
            if (app_rdy & app_en)
              app_addr[26:3] <= app_addr[26:3]+1  ; // app_addr[10:3] +1'b1 ;  8 data ,16bits

        end 


    else     begin        
        if (cstate == 2)
            begin 
               
                 if (num <BURST_RD_128BIT)
                   app_en <= 1'b1 ;
                 else 
                   app_en <= 1'b0 ;                                  
                if  (app_rdy&app_en) begin  
                   app_cmd <= 3'b001 ;                              
                   app_addr[26:3] <= app_addr[26:3] + 1 ;
                   end
            end 
        else 
            begin 
                app_cmd <= 3'd0 ;
                app_en   <= 1'b0 ;
                app_addr <= 27'd0 ;
            end 

    end
end 
                  
//   

always @ ( posedge clk)
    if (!rst_n)
        begin 
            app_wdf_data <= 128'd0 ;
            app_wdf_mask<=16'd0;
            app_wdf_wren <= 0 ;
        end 
    else 
        begin
             app_wdf_mask<=16'd0; 
            if(cstate == 1)
                begin
                      app_wdf_data <= DATA ;//prepare the data
                     if (wrnum <= BURST_WR_128BIT )
                          app_wdf_wren <= 1'b1 ;
                      else 
                          app_wdf_wren <= 1'b0 ;
                          
                    if (app_wdf_rdy & app_wdf_wren)
                            app_wdf_data <= DATA ;                                 
                end 
            else 
              begin 
                app_wdf_data <= 128'd0 ;
                app_wdf_wren <= 0      ;
              end 
        end
               
assign  app_wdf_end = 1'b1;  


always @(posedge clk or negedge rst_n)
    if(!rst_n) begin
        error_flag <= 0;
    end	
    else   begin 
                if(app_rd_data_valid&&(app_rd_data!= DATA))                                             
                    error_flag <= 1 ;	                  
                else error_flag <=0  ;
            end 
            

endmodule 
 

 

 

 

 

 

 

 

 

附件下载

Posted in FPGA, FPGA 教材教案, FPGA硬件资源, Verilog, Vivado, 教材与教案, 文章

5 Comments

  1. 8班王飞飞

    老师好,在学习时遇到一个问题,请老师解答:
    1、本文中定义常量BURST_RD_128BIT=16777216,请问老师这里的数值(16777216)代表什么含义,是如何计算得到的呢?请老师详细讲解一下,谢谢老师!

    • William

      FII-PRX100-D硬件上所使用的DDR芯片型号为MT41J128M16HA-125,容量为256M bytes。BURST_RD_128BIT = 16777216 表示 2 ^24(16777216) * 128bit = 2 ^24 * 128/ 8 bytes = 256M bytes。可以实现对全片进行测试。

  2. 6班李红梅

    老师,请教一下,我们ddr3控制器的地址映射选择的是ROW+BANK+COLUMN, 上面测试程序里面的app_addr[26:3] +1 如果第一行的列地址加完,再加一不是直接加在了bank上面么,按道理应该是这一行的列写完,就应该下一行的第一列开始。地址映射应该是BANK+ROW+COLUMN 才对?

发表回复

相关链接