基于紫光平台AXi+ddr3调试 PG2L100H-6FBG484

小弟最近在调试紫光的ddr3IP,有些心得经验,坐下记录,仅供各位参考
在这里插入图片描述
在这里插入图片描述

DDR3存储构架设计:
DDR3型号 :MT41K12816MXX;
DDR3存储空间:16M x 16bits x 8Banks = 8Banks x 16384 x 128 x 8 x 16bits;也就是单片共8个Bank、每Bank共16384个Row地址、每Row共128个Col地址、每Col为128bits = 8x16bits。
由上述描述
本次DDR3读写的存储空间设计存储空间划分如下:在一个bank内通过发送5000多个16bit的自加数验证读写,验证ddr3读写,这样简单的读写,轮询机制只需要对两个通道进行仲裁,数据读写各占一个通道,

对于ddr3写操作,由于选用连续的读写方式,这样每次写完一行,在去写下一行
在这里插入图片描述
ddr3_ipcore
这样总体在顶层需要一个AXI接口模块ddr3_ctrl方便我们控制ddr3的读写,控制状态机的跳转用来实现数据的写入和读出
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

由ddr_ctrl模块按照紫光简化的AXI协议(如下图)控制ddr3_IP读地址通道,写地址通道,读数据通道,写数据通道,进行读写操作,包括一些握手信号,突发数据起始地址,突发长度(下图为上板抓取的紫光ddr3 demo时序列):
在这里插入图片描述
ddr3行列以及bank地址划分如下:
在这里插入图片描述

这样一旦ddr_ctrl模块发起读写请求,按照axi协议要求和ddr3握手成功,送出突发长度和起始地址,完成一次突发读写,对于连续的地址只需要按照数据总量和突发长度,需要的突发次数,把一个row的所有col写满后,跳转到下一个row。
本次读写设计中程序架构如下图:
在这里插入图片描述
在设计中顶层模块主要包含ddr3_ctrl用来控制和AXI接口的通信,和ddr3_fifo_ctrl模块的用来控制fifo给AXi接口提供AXI_wdata和AXI_rdata的读写数据,ddr_test用来产生测试的自己数数据

DDR3 IP 核的接口信号很多,下图为ddr3的IP核配置:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
PLL时钟模块配置:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

rd_fifo IP 核参数配置如下图所示:
在这里插入图片描述
wr_fifo IP 核参数配置如下图所示:
在这里插入图片描述

在代码中定义了四个参数,分别为 ddr3 读写起始地址(APP_ADDR_MIN)、 ddr3 读写结束地址(APP_ADDR_MAX)、 ddr3 读写突发长度(BURST_LENGTH) 以及读写 ddr3 的最大数据量(DATA_MAX)。其中 APP_ADDR_MIN、 APP_ADDR_MAX 和 DATA_MAX 是以一个 16bit 的数据为一个单位, BURST_LENGTH 是以一个 128bit 的数据为一个单位。

APP_ADDR_MAX = APP_ADDR_MIN + BURST_LENGTH * 8 * n(n 表示突发次数)

DATA_MAX = APP_ADDR_MAX - APP_ADDR_MIN
在这里插入图片描述
对于突发长度(BURST_LENGTH) 的设置, 根据配置,列地址是 10 位,列地址边界就是 1023,突发结束地址不能超过 1023(即 1024 个字节),超过就需要分两次,分两次的话实测是有可能会发生列地址回滚现象的,即列地址回滚到 0(起始地址) ,覆盖了一部分以 0 为起始地址的数据, 由于 DDR 是硬核 IP,无法规避,只能从应用层控制,所以尽量设置为 2 的整数次幂且不要超过 64(例如 2、 4、 8、 16、 32、 64),以此来规避可能出现的因为回滚造成数据覆盖而导致读写错误问题。
由于 DDR3 控制器被封装成 FIFO 接口,在使用时只需要像 读/写 FIFO 那样给出读/写使能即可,如代码 51 ~ 62 行所示。同时定义了最大和最小读写地址,在调用时数据在该地址空间中连续读写。
指定 DDR3 控制器的数据突发长度,由于 DDR3 IP 核的突发长度位宽为 4 位,因此控制器的突发长度不能大于 16。
ddr3 控制器顶层模块主要完成 ddr3 读写控制器模块、 FIFO 控制模块和 ddr3 IP 核的例化。ddr3读写控制器模块负责与 ddr3 IP 核模块的命令和地址的交互,根据 FIFO 控制模块中 fifo 的剩余数据量来切换 DDR3 的读写命令和地址。 ddr3 IP 核模块一边与用户端进行交互,另一边对芯片进行操作,以实现数据的存储。 FIFO 控制模块负责对输入和输出的数据进行时钟域的切换和位宽的转换。
在这里插入图片描述
代码中计算了最大突发次数,由于是从 0 地址开始写入,所以 lenth_cnt_max = app_addr_wr_max / (wr_bust_len * 8) ;若不是从 0 地址开始写入,则 lenth_cnt_max = (app_addr_wr_max - app_addr_wr_min) / (wr_bust_len * 8) 。
lenth_cnt_max(最大突发次数计数器) 的位宽为 10, 10 位宽的计数器最大可以计数到 1023,而根据上面的公式可以计算出本次读写例程只需要进行 10 次突发, 所以 10 位宽的计数器对于本次实验来说是绰绰有余的,但是当存储更大的数据量时,随着所需突发次数的增加,lenth_cnt_max 的位宽也需要做出相应的增大,否则就会出现读写错误的现象。
在这里插入图片描述
在这里插入图片描述
为了稳定 ddr3 初始化完成信号,因为 ddr3 IP 核对初始化完成信号存在信号校准,所以初始化完成后该信号并非一直保持为高,会有跳动,因此在这里做当检测到一次 ddr3 初始化完成信号后,就将该信号一直拉高,使后续模块运行时, 时序不受影响。
在这里插入图片描述

执行写地址操作, ddr3 初始化完成后,若写地址计数小于最后一次写地址起始位时,如果当前状态机处于写地址状态且写地址准备信号有效,拉高写地址有效信号; 写地址有效信号和写地址准备信号同时为高时,写地址计数器 (axi_awaddr_n) 增加一个突发长度所需的地址并将写地址有效信号拉低,即写地址有效信号只拉高了一个时钟周期。 若写地址计数小于最后一次写地址起始位时,当写地址有效信号和写地址准备信号同时为高时,将写地址计数器清零(即回到写起始地址),其他信号变化相同。
在这里插入图片描述

代码执行写数据操作,ddr3 初始化完成后,若突发写次数计数器小于最大突发次数时,如果当前状态机处于写数据状态且写数据准备信号有效时,拉高写数据有效信号直至完成一次突发写操作后再将其拉低。 因为写 DDR 时已经提前让 FIFO 准备好第一个数据,所以使能在写结尾要减少一个使能周期,因此在写数据有效信号和写数据准备信号同时为高时,若突发长度计数器 (init_addr) 小于突发长度 -2 时,突发长度计数器加 1; 若突发长度计数器 (init_addr) 等于突发长度 -2 (即写倒数第二个数) 时,将 wrfifo_en_ctrl 信号拉高(即在写结尾减少一个使能周期);若突发长度计数器 (init_addr) 等于突发长度 -1 (即写最后一个数) 时,将 wrfifo_en_ctrl 信号拉低,即 wrfifo_en_ctrl 信号只拉高一个时钟周期,为下一次写数据操作做准备。
读地址操作的信号跳转与写地址操作时类似,这里不再赘述。
在这里插入图片描述

在这里插入图片描述
上图为ddr控制模块的状态转移图,在复位结束后,如果 DDR3 没有初始化完成,那么状态一直在空闲状态 (IDLE) ,否则跳到 DDR3 空闲状态 (DDR3_DONE) 。
状态机DDR3_done处理 DDR3 写请求,以免写 FIFO 溢出,造成写入 DDR3 的数据丢失。当写 FIFO 中的数据量大于一次突发写长度时,执行 DDR3 写地址操作 (WRITE_ADDR) 。
状态机DDR3_done处理 DDR3 读请求,以免读 FIFO 读空,造成空读现象。当读 FIFO 中的数据量小于一次读突发长度时,执行 DDR3 读地址操作 (READ_ADDR) 。
处理 DDR3 写地址跳转到写数据状态的过程,当写地址有效信号和写地址准备信号同时为高时,状态机由写地址状态 (WRITE_ADDR) 跳转到写数据状态 (WRITE_DATA) ;当执行完一次突发写长度后,状态机由写数据状态跳转到 DDR3 空闲状态 (DDR3_DONE) 。
处理 DDR3 读地址跳转到读数据状态的过程,跳转机制与写状态类似,有别处在于读数据状态 (READ_DATA) 跳转到 DDR3 空闲状态 (DDR3_DONE) 的条件是最后一次读信号 (axi_rlast) 为 1 时。
该模块例化了两个 FIFO IP 核,分别为 128 位进 16 位出的读 FIFO 和 16 位进 128 位出的写 FIFO。读 FIFO 是将 DDR3 输出的 128 位宽的数据转为 16 位宽的数据后输出给用户;写 FIFO 是将用户输入的 16 位宽的数据转为 128 位宽的数据后输出给 DDR3。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图为上板debug抓取的读写数据时的axi接口时序,以及最后AXI_rdata输出的自加数

ddr3_rw_top代码

module ddr3_rw_top#(
parameter MEM_ROW_WIDTH		= 13    ,
parameter MEM_COLUMN_WIDTH	= 10    ,
parameter MEM_BANK_WIDTH	= 3     ,
parameter MEM_DQ_WIDTH		= 16    ,
parameter MEM_DQS_WIDTH		= 2     ,
parameter DATA_BITS			= MEM_DQ_WIDTH*8
)
(
    input             sys_clk          , //系统时钟50M
    input             sys_rst_n        , //系统复位
    output            led_error        , //读写错误led灯
    output            led_ddr_init_done, //ddr3初始化完成led灯

    //DDR3接口
    output						mem_cs_n,
    output						mem_rst_n,
    output						mem_ck,
    output						mem_ck_n,
    output						mem_cke,
    output						mem_ras_n,
    output						mem_cas_n,
    output						mem_we_n,
    output						mem_odt,
    output [MEM_ROW_WIDTH-1:0]	mem_a,
    output [MEM_BANK_WIDTH-1:0]	mem_ba,
    inout [MEM_DQ_WIDTH/8-1:0]	mem_dqs,
    inout [MEM_DQ_WIDTH/8-1:0]	mem_dqs_n,
    inout [MEM_DQ_WIDTH-1:0]	mem_dq,
    output [MEM_DQ_WIDTH/8-1:0]	mem_dm   
   );

//parameter define 
parameter  APP_ADDR_MIN = 28'd0  ;  //ddr3读写起始地址,以一个16bit的数据为一个单位
//APP_ADDR_MAX = APP_ADDR_MIN + BURST_LENGTH * 8 * n(n表示突发次数)
parameter  APP_ADDR_MAX = 28'd5120 ;  //ddr3读写结束地址,以一个16bit的数据为一个单位
parameter  BURST_LENGTH = 5'd16    ;  //ddr3读写突发长度,64个128bit的数据
parameter  DATA_MAX = APP_ADDR_MAX - APP_ADDR_MIN;  //读写ddr3的最大数据量

//wire define
wire  [15:0]  wr_data        ;  //DDR3控制器模块写数据
wire  [15:0]  rd_data        ;  //DDR3控制器模块读数据
wire          wr_en          ;  //DDR3控制器模块写使能
wire          rd_en          ;  //DDR3控制器模块读使能
wire          ddr_init_done  ;  //ddr3初始化完成信号
wire          error_flag     ;  //ddr3读写错误标志
wire          reset_o        ;
wire          clkout3        ;
//ddr3控制器顶层模块
ddr3_top #(
    .MEM_ROW_WIDTH              (MEM_ROW_WIDTH                ),
    .MEM_COLUMN_WIDTH           (MEM_COLUMN_WIDTH             ),
    .MEM_BANK_WIDTH             (MEM_BANK_WIDTH               ),
    .MEM_DQ_WIDTH               (MEM_DQ_WIDTH                 ),
   
    .MEM_DQS_WIDTH              (MEM_DQS_WIDTH                ),
    .DATA_BITS                  (DATA_BITS                    )
)u_ddr3_top(
 .refclk_in             (sys_clk         ),
 .rst_n                 (sys_rst_n       ),
 .app_addr_rd_min       (APP_ADDR_MIN    ),
 .app_addr_rd_max       (APP_ADDR_MAX    ),
 .rd_bust_len           (BURST_LENGTH   ),
 .app_addr_wr_min       (APP_ADDR_MIN   ),
 .app_addr_wr_max       (APP_ADDR_MAX   ),
 .wr_bust_len           (BURST_LENGTH    ),
 .wr_clk                (sys_clk         ),
 .rd_clk                (sys_clk         ),
 .datain_valid          (wr_en           ),
 .datain                (wr_data         ),
 .rdata_req             (rd_en           ),
 .reset_o               (reset_o         ),
 .dataout               (rd_data         ),
 .init_done         (ddr_init_done   ),
 .clkout3               (clkout3)      ,
 //DDR3接口
 .mem_cs_n                   (mem_cs_n                     ),
 .mem_rst_n                  (mem_rst_n                    ),
 .mem_ck                     (mem_ck                       ),
 .mem_ck_n                   (mem_ck_n                     ),
 .mem_cke                    (mem_cke                      ),
 .mem_ras_n                  (mem_ras_n                    ),
 .mem_cas_n                  (mem_cas_n                    ),
 .mem_we_n                   (mem_we_n                     ),
 .mem_odt                    (mem_odt                      ),
 .mem_a                      (mem_a                        ),
 .mem_ba                     (mem_ba                       ),
 .mem_dqs                    (mem_dqs                      ),
 .mem_dqs_n                  (mem_dqs_n                    ),
 .mem_dq                     (mem_dq                       ),
 .mem_dm                     (mem_dm                       )
 );  

//ddr3测试数据模块  
ddr_test u_ddr_test(
    .clk_50m       (clkout3         ),    //时钟
    .rst_n         (reset_o       ),    //复位,低有效
    .wr_en         (wr_en           ),    //写使能
    .wr_data       (wr_data         ),    //写数据
    .rd_en         (rd_en           ),    //读使能
    .rd_data       (rd_data         ),    //读数据  
    .data_max      (DATA_MAX        ),    //读写ddr的最大数据量
    .ddr3_init_done(ddr_init_done   ),    //ddr3初始化完成信号
    .error_flag    (error_flag      )     //ddr3读写错误
    );

//利用LED灯指示ddr3读写测试的结果及ddr3是否初始化完成
led_disp u_led_disp(
    .clk_50m            (clkout3          ),
    .rst_n              (reset_o        ),
    .ddr3_init_done     (ddr_init_done    ),
    .error_flag         (error_flag       ),
    .led_error          (led_error        ),
    .led_ddr_init_done  (led_ddr_init_done)
    );
	
	
	
	
	
	


endmodule

下面展示一些 内联代码片

ddr3_top代码
module ddr3_top#(
parameter MEM_ROW_WIDTH		= 13    ,
parameter MEM_COLUMN_WIDTH	= 10    ,
parameter MEM_BANK_WIDTH	= 3     ,
parameter MEM_DQ_WIDTH		= 16    ,
parameter MEM_DQS_WIDTH		= 2     ,
parameter DATA_BITS			= MEM_DQ_WIDTH*8
)
(
    input              refclk_in        ,//外部参考时钟输入
    input              rst_n            ,//外部复位输入

    input   [27:0]     app_addr_rd_min  ,//读ddr3的起始地址
    input   [27:0]     app_addr_rd_max  ,//读ddr3的结束地址
    input   [4:0]      rd_bust_len      ,//从ddr3中读数据时的突发长度
    input   [27:0]     app_addr_wr_min  ,//读ddr3的起始地址
    input   [27:0]     app_addr_wr_max  ,//读ddr3的结束地址
    input   [4:0]      wr_bust_len      ,//从ddr3中读数据时的突发长度
    //用户     
    input              wr_clk           ,//wfifo写时钟
    input              rd_clk           ,//rfifo读时钟
    input              datain_valid     ,//数据有效使能信号
    input   [15:0]     datain           ,//有效数据
    input              rdata_req        ,//请求数据输入
	output             reset_o          ,
    output  [15:0]     dataout          ,//rfifo输出数据
    output             clkout3       /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/   ,
    output             init_done    ,//DDR初始化完成
    output						mem_cs_n,
    output						mem_rst_n,
    output						mem_ck,
    output						mem_ck_n,
    output						mem_cke,
    output						mem_ras_n,
    output						mem_cas_n,
    output						mem_we_n,
    output						mem_odt,
    output [MEM_ROW_WIDTH-1:0]	mem_a,
    output [MEM_BANK_WIDTH-1:0]	mem_ba,
    inout [MEM_DQ_WIDTH/8-1:0]	mem_dqs,
    inout [MEM_DQ_WIDTH/8-1:0]	mem_dqs_n,
    inout [MEM_DQ_WIDTH-1:0]	mem_dq,
    output [MEM_DQ_WIDTH/8-1:0]	mem_dm 
   );
parameter CTRL_ADDR_WIDTH	= MEM_ROW_WIDTH + MEM_BANK_WIDTH + MEM_COLUMN_WIDTH;
wire                         core_clk                 /* synthesis syn_keep = 1 */ ;
wire                         pll_lock                 /* synthesis syn_keep = 1 */ ;
wire                         phy_pll_lock             /* synthesis syn_keep = 1 */ ;
wire                         gpll_lock                /* synthesis syn_keep = 1 */ ;
wire                         rst_gpll_lock            /* synthesis syn_keep = 1 */ ;
wire                         ddrphy_cpd_lock          /* synthesis syn_keep = 1 */ ;
wire                         ddr_init_done            /* synthesis syn_keep = 1 */ ;
wire               sys_rst;
wire		rst;
wire		rstn;
wire		core_rst;
wire		core_rstn;
//wire define
    wire  [25:0]      axi_awaddr   /* synthesis syn_keep = 1 */ ;
    wire  [3:0]       axi_awlen   /* synthesis syn_keep = 1 */    ;

 

    wire              axi_awready   /* synthesis syn_keep = 1 */;
    wire              axi_awvalid  /* synthesis syn_keep = 1 */ ;

    wire  [127:0]   axi_wdata  ;
    wire  [15:0]    axi_wstrb /* synthesis syn_keep = 1 */     ;
    wire              axi_wvalid /* synthesis syn_keep = 1 */ ;
    wire              axi_wready/* synthesis syn_keep = 1 */;


    wire  [25:0]      axi_araddr   /* synthesis syn_keep = 1 */ ;
    wire  [3:0]       axi_arlen/* synthesis syn_keep = 1 */;




 
    wire              axi_arready/* synthesis syn_keep = 1 */;
    wire              axi_arvalid/* synthesis syn_keep = 1 */;
    wire  [127:0]   axi_rdata      ;
    wire              axi_rlast   /* synthesis syn_keep = 1 */   ;
    wire              axi_rvalid   /* synthesis syn_keep = 1 */  ;
  
  
	
	reg               s_rst_n = 1'b0;
    reg   [7:0]       s_cnt = 8'd0;
    wire              resetn/* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/;
	
	
wire                         axi_awuser_ap             /* synthesis syn_keep = 1 */ ;
wire [3:0]                   axi_awuser_id             /* synthesis syn_keep = 1 */ ;




wire [3:0]                   axi_wusero_id             /* synthesis syn_keep = 1 */ ;
wire                         axi_wusero_last           /* synthesis syn_keep = 1 */ ;

wire                         axi_aruser_ap             /* synthesis syn_keep = 1 */ ;
wire [3:0]                   axi_aruser_id             /* synthesis syn_keep = 1 */ ;

wire [3:0]                   axi_rid                   /* synthesis syn_keep = 1 */ ;

    wire [10:0]       wfifo_rcount   ;//rfifo剩余数据计数
    wire [10:0]       rfifo_wcount   ;//wfifo写进数据计数
    wire              wrfifo_en_ctrl ;//写FIFO数据读使能控制位
    wire              wfifo_rden     ;//写FIFO数据读使能
    wire              pre_wfifo_rden ;//写FIFO数据预读使能
wire [29:0]                  debug_calib_ctrl          ;
wire [1:0]                   dbg_dll_upd_state         ;
wire [17*MEM_DQS_WIDTH -1:0] dbg_slice_status          ;
wire [22*MEM_DQS_WIDTH -1:0] dbg_slice_state           ;
wire [66*MEM_DQS_WIDTH -1:0] debug_data                ;
wire [8:0]                   debug_gpll_dps_phase      ;
wire [2:0]                   dbg_rst_dps_state         ;
wire [5:0]                   dbg_tran_err_rst_cnt      ;
wire                         dbg_ddrphy_init_fail      ;
wire [9:0]                   debug_dps_cnt_dir0        ;
wire [9:0]                   debug_dps_cnt_dir1        ;
wire [7:0]					 ck_dly_set_bin			   ;
wire                         align_error               ;
wire [3:0]                   debug_rst_state           ;
wire [3:0]                   debug_cpd_state           ;
wire		clk_inbuf;
wire		pll_sys_lock;
wire		pll_sys_rst;
wire		pll_led_lock;
wire		pll_led_rst;
wire		sys_clk /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/;
wire        phy0_tx_clk;
wire        phy0_tx_clk;
wire        ref_clk /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/ ;
//*****************************************************
//**                    main code
//*****************************************************
//因为预读了一个数据所以读使能wfifo_rden要少一个周期通过wrfifo_en_ctrl控制
assign ref_clk    = refclk_in;
assign wfifo_rden = axi_wvalid && axi_wready && (~wrfifo_en_ctrl) ;
assign pre_wfifo_rden = axi_awvalid && axi_awready ;
assign init_done      = ddr_init_done;
assign resetn = s_rst_n;
GTP_CLKBUFG U_CLKBUFG (
.CLKOUT (clk_inbuf),
.CLKIN (refclk_in)
);



pll_sys pll_sys_inst (
	.clkin1		(clk_inbuf),	// input
	.rst		(pll_sys_rst),	// input
	.lock		(pll_sys_lock),	// output
	
	.clkout0	(sys_clk),		// output
	.clkout1	(phy0_tx_clk),	// output
	.clkout2	(phy1_tx_clk),	// output
	.clkout3    (clkout3)
);

always @(posedge clk_inbuf) begin
    if(s_cnt == 8'hff) begin
        s_rst_n = 1'b1;
        s_cnt <= s_cnt;
    end
    else
        s_cnt <= s_cnt + 8'd1;
end


sys_rst u_sys_rst(
	.clk				(clk_inbuf),

	.pll_sys_lock		(pll_sys_lock),
	.pll_sys_rst		(pll_sys_rst),

	.pll_led_lock		(pll_led_lock),
	.pll_led_rst		(pll_led_rst),

	.pll_lock			(pll_lock),
	.phy_pll_lock		(phy_pll_lock),
	.gpll_lock			(gpll_lock),
	.rst_gpll_lock		(rst_gpll_lock),
	.ddrphy_cpd_lock	(ddrphy_cpd_lock),
	.ddr_init_done		(ddr_init_done),
	.ddr_core_rstn		(ddr_core_rstn),

	.sys_rst			(sys_rst)
);
ddr3_rst_ctrl u_ddr3_rst_ctrl
(
	.clk			(sys_clk),
	.core_clk		(core_clk),
	.rst_in			(sys_rst),
	
	.rst_o			(rst),
	.rstn_o			(rstn),
	.core_rst_o		(core_rst),
	.reset_o        (reset_o),
	.core_rstn_o	(core_rstn)
);
//ddr3读写控制器模块
rw_ctrl_128bit u_rw_ctrl_128bit
(
 .clk                 (core_clk          ),
 .rst_n               (core_rstn            ),
 .ddr_init_done       (ddr_init_done    ),
 .axi_awaddr          (axi_awaddr       ),
 .axi_awlen           (axi_awlen        ),

 
 .axi_awready         (axi_awready      ),
 .axi_awvalid         (axi_awvalid      ),

 .axi_wstrb           (axi_wstrb        ),
 .axi_wvalid          (axi_wvalid       ),
 .axi_wready          (axi_wready       ),
 //.axi_wlast           (axi_wlast        ),

 .wrfifo_en_ctrl      (wrfifo_en_ctrl   ),
 .axi_araddr          (axi_araddr       ),
 .axi_arlen           (axi_arlen        ),

 .axi_arready         (axi_arready      ),
 .axi_arvalid         (axi_arvalid      ),
 .axi_rlast           (axi_rlast        ),
 .axi_rvalid          (axi_rvalid       ),

 .wfifo_rcount        (wfifo_rcount     ),
 .rfifo_wcount        (rfifo_wcount     ),
 .app_addr_rd_min     (app_addr_rd_min  ),
 .app_addr_rd_max     (app_addr_rd_max  ),
 .rd_bust_len         (rd_bust_len      ),
 .app_addr_wr_min     (app_addr_wr_min  ),
 .app_addr_wr_max     (app_addr_wr_max  ),
 .wr_bust_len         (wr_bust_len      )
 );

ddr3_ipcore #(
    .MEM_ROW_WIDTH              (MEM_ROW_WIDTH                ),
    .MEM_COLUMN_WIDTH           (MEM_COLUMN_WIDTH             ),
    .MEM_BANK_WIDTH             (MEM_BANK_WIDTH               ),
    .MEM_DQ_WIDTH               (MEM_DQ_WIDTH                 ),
    .MEM_DM_WIDTH               (MEM_DQS_WIDTH                ),
    .MEM_DQS_WIDTH              (MEM_DQS_WIDTH                ),
    .CTRL_ADDR_WIDTH            (CTRL_ADDR_WIDTH              )
)u_ddr3_ipcore(
    .ref_clk                    (ref_clk                      ),
    .resetn                     (resetn                       ),
	//.resetn                     (ddr_core_rstn),
    .core_clk                   (core_clk                     ),
    .pll_lock                   (pll_lock                     ),
    .phy_pll_lock               (phy_pll_lock                 ),
    .gpll_lock                  (gpll_lock                    ),
    .rst_gpll_lock              (rst_gpll_lock                ),
    .ddrphy_cpd_lock            (ddrphy_cpd_lock              ),
    .ddr_init_done              (ddr_init_done                ),

    .axi_awaddr                 (axi_awaddr                   ),
    .axi_awuser_ap              (1'b0                ),
    .axi_awuser_id              (4'd0                ),
    .axi_awlen                  (axi_awlen                    ),
    .axi_awready                (axi_awready                  ),
    .axi_awvalid                (axi_awvalid                  ),

    .axi_wdata                  (axi_wdata                    ),
    .axi_wstrb                  (axi_wstrb                    ),
    .axi_wready                 (axi_wready                   ),
    .axi_wusero_id              (axi_wusero_id                ),
    .axi_wusero_last            (axi_wusero_last              ),

    .axi_araddr                 (axi_araddr                   ),
    .axi_aruser_ap              (1'b0                ),
    .axi_aruser_id              (4'd0                ),
    .axi_arlen                  (axi_arlen                    ),
    .axi_arready                (axi_arready                  ),
    .axi_arvalid                (axi_arvalid                  ),

    .axi_rdata                  (axi_rdata                    ),
    .axi_rid                    (axi_rid                      ),
    .axi_rlast                  (axi_rlast                    ),
    .axi_rvalid                 (axi_rvalid                   ),

    .apb_clk                    (1'b0                         ),
    .apb_rst_n                  (1'b0                         ),
    .apb_sel                    (1'b0                         ),
    .apb_enable                 (1'b0                         ),
    .apb_addr                   (8'd0                         ),
    .apb_write                  (1'b0                         ),
    .apb_ready                  (                             ),
    .apb_wdata                  (16'd0                        ),
    .apb_rdata                  (                             ),
	
    .mem_cs_n                   (mem_cs_n                     ),
    .mem_rst_n                  (mem_rst_n                    ),
    .mem_ck                     (mem_ck                       ),
    .mem_ck_n                   (mem_ck_n                     ),
    .mem_cke                    (mem_cke                      ),
    .mem_ras_n                  (mem_ras_n                    ),
    .mem_cas_n                  (mem_cas_n                    ),
    .mem_we_n                   (mem_we_n                     ),
    .mem_odt                    (mem_odt                      ),
    .mem_a                      (mem_a                        ),
    .mem_ba                     (mem_ba                       ),
    .mem_dqs                    (mem_dqs                      ),
    .mem_dqs_n                  (mem_dqs_n                    ),
    .mem_dq                     (mem_dq                       ),
    .mem_dm                     (mem_dm                       ),
	
    .dbg_gate_start             (1'b0                         ),
    .dbg_cpd_start              (1'b0                         ),
    .dbg_ddrphy_rst_n           (1'b1                         ),
    .dbg_gpll_scan_rst          (1'b0                         ),
    .samp_position_dyn_adj      (1'b0                         ),
    .init_samp_position_even    (32'b0                        ),
    .init_samp_position_odd     (32'b0                        ),
    .wrcal_position_dyn_adj     (1'b0                         ),
    .init_wrcal_position        (32'b0                        ),
    .force_read_clk_ctrl        (1'b0                         ),
    .init_slip_step             (16'b0                        ),
    .init_read_clk_ctrl         (12'b0                        ),
    .debug_calib_ctrl           (debug_calib_ctrl             ),
    .dbg_dll_upd_state          (dbg_dll_upd_state            ),
    .dbg_slice_status           (dbg_slice_status             ),
    .dbg_slice_state            (dbg_slice_state              ),
    .debug_data                 (debug_data                   ),
    .debug_gpll_dps_phase       (debug_gpll_dps_phase         ),
    .dbg_rst_dps_state          (dbg_rst_dps_state            ),
    .dbg_tran_err_rst_cnt       (dbg_tran_err_rst_cnt         ),
    .dbg_ddrphy_init_fail       (dbg_ddrphy_init_fail         ),
    .debug_cpd_offset_adj       (1'b0                         ),
    .debug_cpd_offset_dir       (1'b0                         ),
    .debug_cpd_offset           (10'b0                        ),
    .debug_dps_cnt_dir0         (debug_dps_cnt_dir0           ),
    .debug_dps_cnt_dir1         (debug_dps_cnt_dir1           ),
    //.ck_dly_set_bin             (8'h32                        ),//延迟设置 步进5ps 目前为250ps
	.ck_dly_en                  (1'b1                         ),
	.init_ck_dly_step           (8'h00                        ),
	.ck_dly_set_bin             (ck_dly_set_bin               ),
    .align_error                (align_error                  ),
    .debug_rst_state            (debug_rst_state              ),
    .debug_cpd_state            (debug_cpd_state              )
);

//ddr3控制器fifo控制模块
 ddr3_fifo_ctrl u_ddr3_fifo_ctrl (
    .rst_n               (sys_rst && ddr_init_done    ) ,  //复位
    //输入源接口
    .wr_clk              (sys_clk                    ) ,  //写时钟
    .rd_clk              (sys_clk                    ) ,  //读时钟
    .clk_100             (core_clk                   ) ,  //用户时钟 
    .datain_valid        (datain_valid              ) ,  //数据有效使能信号
    .datain              (datain                    ) ,  //有效数据 
    .rfifo_din           (axi_rdata                 ) ,  //用户读数据 
    .rdata_req           (rdata_req                 ) ,  //请求像素点颜色数据输入
    .rfifo_wren          (axi_rvalid                ) ,  //ddr3读出数据的有效使能
    .wfifo_rden          (wfifo_rden ) ,  //ddr3 写使能
    //用户接口
    .wfifo_rcount        (wfifo_rcount              ) , //rfifo剩余数据计数
    .rfifo_wcount        (rfifo_wcount              ) , //wfifo写进数据计数
    .wfifo_dout          (axi_wdata                 ) , //用户写数据
    .pic_data            (dataout                   )   //rfifo输出数据
    );

endmodule

下面展示一些 内联代码片

系统 复位代码
`timescale 1ns / 1ps


module sys_rst (
	input wire		clk,
	
	input wire		pll_sys_lock,
	output wire		pll_sys_rst,
	
	input wire		pll_led_lock,
	output wire		pll_led_rst,
	
	input wire		pll_lock,
	input wire		phy_pll_lock,
	input wire		gpll_lock,
	input wire		rst_gpll_lock,
	input wire		ddrphy_cpd_lock,
	input wire		ddr_init_done,
	output wire		ddr_core_rstn,
	
	output wire		sys_rst
);
//----------------------------------- parameter ------------------------------------
//==================================================================================
//---------------------------------- reg / wire ------------------------------------
reg [15:0]	pll_sys_lockcnt = 16'h0000;
reg			pll_sys_restart ;
reg			pll_sys_rst_temp ;

reg [15:0]	pll_led_lockcnt = 16'h0000;
reg			pll_led_restart ;
reg			pll_led_rst_temp ;

reg			ddr_all_lock;
reg [19:0]	ddr_lockcnt = 20'h00000;
reg			ddr_restart ;
reg			ddr_rst_temp ;

reg [15:0]	sys_rstcnt = 16'h0000;
reg			sys_rst_temp ;

//==================================================================================
//------------------------------- global code design -------------------------------
//==================================================================================

//----------------------------------- code design ----------------------------------

//pll_sys
always@(posedge clk)
begin
	if(pll_sys_restart)
		pll_sys_lockcnt <= 16'd0 ;
	else if(pll_sys_lockcnt < 60000)
		pll_sys_lockcnt <= pll_sys_lockcnt + 1 ;
end

always@(posedge clk)
begin
	if(pll_sys_lockcnt < 50000)		//1ms
		pll_sys_restart <= 0 ;
	else if(~pll_sys_lock)
		pll_sys_restart <= 1 ;
	else
		pll_sys_restart <= 0 ;
end

always@(posedge clk)
begin
	if(pll_sys_lockcnt < 8)			//160ns > min10ns
		pll_sys_rst_temp <= 1 ;
	else
		pll_sys_rst_temp <= 0 ;
end

assign pll_sys_rst = pll_sys_rst_temp ;

//pll_led
always@(posedge clk)
begin
	if(pll_led_restart)
		pll_led_lockcnt <= 16'd0 ;
	else if(pll_led_lockcnt < 60000)
		pll_led_lockcnt <= pll_led_lockcnt + 1 ;
end

always@(posedge clk)
begin
	if(pll_led_lockcnt < 50000)		//1ms
		pll_led_restart <= 0 ;
	else if(~pll_led_lock)
		pll_led_restart <= 1 ;
	else
		pll_led_restart <= 0 ;
end

always@(posedge clk)
begin
	if(pll_led_lockcnt < 8)			//160ns > min10ns
		pll_led_rst_temp <= 1 ;
	else
		pll_led_rst_temp <= 0 ;
end

assign pll_led_rst = pll_led_rst_temp ;

//ddr	
always@(posedge clk)
begin
	ddr_all_lock <= ddr_init_done & pll_lock & phy_pll_lock & gpll_lock & rst_gpll_lock & ddrphy_cpd_lock ;
end

always@(posedge clk)
begin
	if(ddr_restart)
		ddr_lockcnt <= 16'd0 ;
	else if(ddr_lockcnt < 600000)
		ddr_lockcnt <= ddr_lockcnt + 1 ;
end

always@(posedge clk)
begin
	if(ddr_lockcnt < 500000)		//10ms
		ddr_restart <= 0 ;
	else if(~ddr_all_lock)
		ddr_restart <= 1 ;
	else
		ddr_restart <= 0 ;
end

always@(posedge clk)
begin
	if(ddr_lockcnt < 25000)			//500us
		ddr_rst_temp <= 0 ;
	else
		ddr_rst_temp <= 1 ;
end

assign ddr_core_rstn = ddr_rst_temp ;

//sys_rst

always@(posedge clk)
begin
	if((~ddr_all_lock)||(~pll_sys_lock)||(~pll_led_lock))
		sys_rstcnt <= 16'd0 ;
	else if(sys_rstcnt < 65500)
		sys_rstcnt <= sys_rstcnt + 1 ;
end

always@(posedge clk)
begin
	if(sys_rstcnt < 100)
		sys_rst_temp <= 1'b0 ;
	else if(sys_rstcnt < 200)
		sys_rst_temp <= 1'b1 ;
	else
		sys_rst_temp <= 1'b0 ;
end

assign sys_rst = sys_rst_temp ;
//==================================================================================

endmodule

下面展示一些 内联代码片

ddr3 复位代码
`timescale 1ns / 1ps
module ddr3_rst_ctrl
(
input wire			clk			,
input wire			core_clk	,
input wire			rst_in		,

output wire			rst_o		,
output wire			rstn_o		,
output wire			core_rst_o	,
output wire         reset_o     ,

output wire			core_rstn_o
);
//----------------------------------- parameter ------------------------------------
//==================================================================================
//---------------------------------- reg / wire ------------------------------------
wire		rstn_in;
assign		rstn_in = ~rst_in;
reg [7:0]	rst_cnt;
reg			rst;
reg [7:0]	core_rst_cnt;
reg			core_rst;
//==================================================================================
//------------------------------- global code design -------------------------------
//==================================================================================
//----------------------------------- code design ----------------------------------
always@(posedge clk or negedge rstn_in)
begin
	if(~rstn_in)
		rst_cnt <= 8'd0 ;
	else if(rst_cnt<255)
		rst_cnt <= rst_cnt + 1 ;
end

always@(posedge clk)
begin
	if(rst_cnt<200)
		rst <= 1'b1 ;
	else
		rst <= 1'b0 ;
end

assign rst_o = rst;
assign rstn_o = ~rst;

//always@(posedge core_clk or negedge rstn_in)
//begin
//	if(~rstn_in)
//		core_rst_cnt <= 8'd0 ;
//	else if(core_rst_cnt<255)
//		core_rst_cnt <= core_rst_cnt + 1 ;
//end
//
//always@(posedge core_clk)
//begin
//	if(core_rst_cnt<200)
//		core_rst <= 1'b1 ;
//	else
//		core_rst <= 1'b0 ;
//end

assign core_rst_o = rst;
assign core_rstn_o = ~rst;
assign reset_o = ~rst;
//==================================================================================

endmodule

下面展示一些 内联代码片

ddr3控制模块代码
module rw_ctrl_128bit
(
   input   wire                 clk             , //时钟
   input   wire                 rst_n           , //复位
   input   wire                 ddr_init_done   , //DDR初始化完成
   output  wire    [25:0]   	axi_awaddr      , //写地址
   output  wire    [3:0]        axi_awlen       , //写突发长度
  
   input   wire                  axi_awready     , //写地址准备信号
   output  wire                  axi_awvalid     , //写地址有效信号

   output  wire    [15:0]        axi_wstrb       , //写选通
   output  wire                  axi_wvalid      , //写数据有效信号
   input   wire                  axi_wready      , //写数据准备信号
   //output reg              axi_wlast       , //最后一次写信号
  
   output  wire                  wrfifo_en_ctrl  , //写FIFO数据读使能控制位
   output  wire    [25:0]        axi_araddr      , //读地址
   output  wire    [3:0]         axi_arlen       , //读突发长度
   
   
   input   wire                  axi_arready     , //读地址准备信号
   output  wire                  axi_arvalid     , //读地址有效信号
   input   wire                  axi_rlast       , //最后一次读信号
   input   wire                  axi_rvalid      , //读数据有效信号
   
   input  wire     [10:0]   wfifo_rcount  /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  , //写端口FIFO中的数据量
   input  wire     [10:0]   rfifo_wcount  /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  , //读端口FIFO中的数据量
   input  wire     [27:0]   app_addr_rd_min , //读DDR3的起始地址
   input  wire     [27:0]   app_addr_rd_max , //读DDR3的结束地址
   input  wire     [4:0]    rd_bust_len /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/    , //从DDR3中读数据时的突发长度
   input  wire     [27:0]   app_addr_wr_min /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/ , //写DDR3的起始地址
   input  wire     [27:0]   app_addr_wr_max /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/ , //写DDR3的结束地址
   input  wire     [4:0]   wr_bust_len /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/     
);

//localparam define 
localparam  IDLE        = 4'b0001 , //空闲状态
			DDR3_DONE   = 4'b0010 , //DDR3初始化完成状态
			WRITE_ADDR  = 4'b0011 , //写地址
			WRITE_DATA  = 4'b0100 , //写数据
			READ_ADDR   = 4'b0101 , //读地址
			READ_DATA   = 4'b0110 ; //读数据

//reg define
reg        init_start /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ; //初始化完成信号
reg [31:0] init_addr    ; //突发长度计数器
reg [27:0] axi_araddr_n ; //读地址计数
reg [27:0] axi_awaddr_n /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/; //写地址计数
reg [3:0] state_cnt  /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ; //状态计数器
reg [3:0] next_state_cnt  /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ; //状态计数器
reg [9:0] lenth_cnt    ; //突发写次数计数器

reg    [4:0]     	 axi_awlen_temp     /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/   ;
reg                  axi_awvalid_temp     ;
reg                  axi_wvalid_temp      ;
reg                  wrfifo_en_ctrl_temp  ;
reg    [4:0]     	 axi_arlen_temp /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ;
reg                  axi_arvalid_temp     ;



//wire define
wire [9:0] lenth_cnt_max; //最大突发次数

//*****************************************************
//**                    main code
//*****************************************************


assign  axi_wstrb    = {16{1'b1}};



//计算最大突发次数
assign  lenth_cnt_max = app_addr_wr_max / (wr_bust_len * 4'd8);

//读写地址,16bit对应一个地址转换为一个字节对应一个地址
assign  axi_araddr = {1'b0,axi_araddr_n[24:0]};
assign  axi_awaddr = {1'b0,axi_awaddr_n[24:0]};

assign axi_awlen = axi_awlen_temp[3:0];
assign axi_awvalid = axi_awvalid_temp;
assign axi_wvalid = axi_wvalid_temp;
assign wrfifo_en_ctrl = wrfifo_en_ctrl_temp;
assign axi_arlen = axi_arlen_temp[3:0];
assign axi_arvalid = axi_arvalid_temp;
//稳定ddr3初始化信号
always @(posedge clk ) begin
    if (rst_n == 1'd0) 
        init_start <= 1'b0;
    else if (ddr_init_done)
        init_start <= ddr_init_done;
    else
        init_start <= init_start;
end

//写地址模块
always @(posedge clk ) begin
    if (rst_n == 1'd0) begin
        axi_awaddr_n <= app_addr_wr_min;
        axi_awlen_temp    <= 5'b0;
        axi_awvalid_temp  <= 1'b0;
    end
    //DDR3初始化完成 
    else if (init_start) begin
        axi_awlen_temp <= wr_bust_len - 1'b1;
        //当写地址计数小于最后一次写地址起始位时
        if (axi_awaddr_n < app_addr_wr_max - wr_bust_len * 5'd8) begin
            //写地址有效信号和写地址准备信号都为1时
            if (axi_awvalid_temp && axi_awready) begin
                axi_awvalid_temp  <= 1'b0;         //拉低写地址有效信号
                //写地址计数加一个突发长度所需的地址
                axi_awaddr_n <= axi_awaddr_n + wr_bust_len * 5'd8;//wr_bust_len*128/16
            end
            //状态机处于写地址状态且写地址准备信号为1时
            else if (state_cnt == WRITE_ADDR )
                axi_awvalid_temp  <= 1'b1;    //拉高写地址有效信号
        end
        //当写地址计数等于最后一次写地址起始位时
        else if (axi_awaddr_n == app_addr_wr_max - wr_bust_len * 5'd8) begin
            if (axi_awvalid_temp && axi_awready) begin
                axi_awvalid_temp  <= 1'b0;
                axi_awaddr_n <= app_addr_wr_min; //写地址计数清零(回到写起始地址)
            end
            else if (state_cnt == WRITE_ADDR)
                axi_awvalid_temp  <= 1'b1;
        end
        else
            axi_awvalid_temp <= 1'b0;
    end 
    else begin
            axi_awaddr_n <= axi_awaddr_n;
            axi_awlen_temp    <= 5'b0;
            axi_awvalid_temp  <= 1'b0;
    end
end

//写数据模块
always @(posedge clk ) begin
    if (rst_n == 1'd0) begin
        axi_wvalid_temp <= 1'b0  ;
        //axi_wlast  <= 1'b0  ;
        init_addr  <= 32'd0 ;
        lenth_cnt  <= 8'd0  ;
        wrfifo_en_ctrl_temp <= 1'b0;
    end
    else begin
        //DDR3初始化完成
        if (init_start) begin
            //当突发写次数计数器小于最大突发次数时
            if (lenth_cnt < lenth_cnt_max) begin
                if (axi_wvalid_temp && axi_wready && init_addr < wr_bust_len - 2'd2) begin
                    init_addr      <= init_addr + 1'b1;
                    wrfifo_en_ctrl_temp <= 1'b0;
                end 
                //因为写DDR时已经提前让FIFO准备好第一个数据,所以使能在写结尾要减少一个使能周期
                else if (axi_wvalid_temp && axi_wready && init_addr == wr_bust_len - 2'd2) begin
                    //axi_wlast      <= 1'b1;
                    wrfifo_en_ctrl_temp <= 1'b1;              //提前一个时钟周期拉高
                    init_addr      <= init_addr + 1'b1;
                end
                //当突发长度计数器等于一次突发长度时
                else if (axi_wvalid_temp && axi_wready && init_addr == wr_bust_len - 2'd1) begin
                    axi_wvalid_temp     <= 1'b0;
                    //axi_wlast      <= 1'b0;
                    wrfifo_en_ctrl_temp <= 1'b0;
                    lenth_cnt      <= lenth_cnt + 1'b1;  //突发写次数计数器加1
                    init_addr      <= 32'd0;
                end         
                else if (state_cnt == WRITE_DATA )
                    axi_wvalid_temp     <= 1'b1;
                else 
                    lenth_cnt      <= lenth_cnt;
            end
            else begin
                axi_wvalid_temp <= 1'b0     ;
//axi_wlast  <= 1'b0     ;
                init_addr  <= init_addr;
                lenth_cnt  <= 8'd0     ;
            end
        end
        else begin
            axi_wvalid_temp <= 1'b0 ;
           // axi_wlast  <= 1'b0 ;
            init_addr  <= 32'd0;
            lenth_cnt  <= 8'd0 ;
        end
    end
end 

//读地址模块
always @(posedge clk ) begin
    if (rst_n == 1'd0) begin
      axi_araddr_n <= app_addr_rd_min;
      axi_arlen_temp    <= 5'b0;
      axi_arvalid_temp  <= 1'b0;
    end
    //DDR3初始化完成
    else if(init_start) begin
        axi_arlen_temp <= rd_bust_len - 1'b1;
        //当读地址计数小于最后一次读地址起始位时
        if (axi_araddr_n < app_addr_rd_max  - rd_bust_len * 5'd8) begin
            if (axi_arready && axi_arvalid_temp) begin
                axi_arvalid_temp  <= 1'b0;
                axi_araddr_n <= axi_araddr_n + rd_bust_len * 5'd8;
            end
            else if(state_cnt == READ_ADDR)
                axi_arvalid_temp  <= 1'b1;
        end 
        //当读地址计数等于最后一次读地址起始位时
        else if (axi_araddr_n == app_addr_rd_max - rd_bust_len * 5'd8) begin
            if (axi_arready && axi_arvalid_temp) begin
                axi_arvalid_temp  <= 1'b0;
                axi_araddr_n <= app_addr_rd_min;
            end
            else if(state_cnt==READ_ADDR)
                axi_arvalid_temp  <= 1'b1;
        end             
        else
            axi_arvalid_temp <= 1'b0;
    end
    else begin  
            axi_araddr_n   <= app_addr_rd_min;
            axi_arlen_temp      <= 5'b0;
            axi_arvalid_temp    <= 1'b0;
    end     
end 

//DDR3读写逻辑实现模块


always@(posedge clk)
begin
	if(rst_n == 1'd0)
		state_cnt <= IDLE;
	else
		state_cnt <= next_state_cnt;
		
end
always @(*) begin
    
        case(state_cnt)
            IDLE:begin
                if(init_start)
                    next_state_cnt <= DDR3_DONE ;
                else
                    next_state_cnt <= IDLE;
            end
            DDR3_DONE:begin
                if(wfifo_rcount >= wr_bust_len)
                    next_state_cnt <= WRITE_ADDR;         //跳到写地址操作
                else if(rfifo_wcount < rd_bust_len)
                    next_state_cnt <= READ_ADDR;          //跳到读地址操作
                else 
                    next_state_cnt <= DDR3_DONE; 
            end             
            WRITE_ADDR:begin
                if(axi_awvalid_temp && axi_awready)
                    next_state_cnt <= WRITE_DATA;        //跳到写数据操作 
                else
                    next_state_cnt <= WRITE_ADDR;         //条件不满足,保持当前值
            end
            WRITE_DATA:begin 
                if(axi_wvalid_temp && axi_wready && init_addr == wr_bust_len - 1)
                    next_state_cnt <= DDR3_DONE;        //写到设定的长度跳到等待状态
                else
                    next_state_cnt <= WRITE_DATA;        //写条件不满足,保持当前值
            end         
            READ_ADDR:begin
                if(axi_arvalid_temp && axi_arready)
                    next_state_cnt <= READ_DATA;        //跳到读数据操作
                else
                    next_state_cnt <= READ_ADDR;        //条件不满足,保持当前值
            end
            READ_DATA:begin
                if(axi_rlast)                      //读到设定的地址长度
                    next_state_cnt <= DDR3_DONE;        //则跳到空闲状态
                else
                    next_state_cnt <= READ_DATA;        //否则保持当前值
            end
            default:begin
                next_state_cnt <= IDLE;
            end
        endcase
    
end

endmodule

下面展示一些 内联代码片

ddr3 fifo 控制模块
module ddr3_fifo_ctrl(
    input           rst_n            ,  //复位信号
    input           wr_clk           ,  //wfifo时钟
    input           rd_clk        /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/   ,  //rfifo时钟
    input           clk_100          ,  //用户时钟
    input           datain_valid     ,  //数据有效使能信号
    input  [15:0]   datain           ,  //有效数据
    input  [127:0]  rfifo_din        ,  //用户读数据
    input           rdata_req        ,  //请求像素点颜色数据输入
    input           rfifo_wren       ,  //从ddr3读出数据的有效使能
    input           wfifo_rden       ,  //wfifo读使能
    output [127:0]  wfifo_dout       ,  //用户写数据
    output [10:0]   wfifo_rcount     ,  //rfifo剩余数据计数
    output [10:0]   rfifo_wcount     ,  //wfifo写进数据计数
    output [15:0]   pic_data            //有效数据
    );

rd_fifo u_rd_fifo  (
  .wr_clk         (clk_100     ),  // input
  .wr_rst         (rst_n      ),  // input
  .wr_en          (rfifo_wren  ),  // input
  .wr_data        (rfifo_din   ),  // input [127:0]
  .wr_full        (            ),  // output
  .wr_water_level (rfifo_wcount),  // output
  .almost_full    (            ),  // output
  .rd_clk         (rd_clk      ),  // input
  .rd_rst         (rst_n      ),  // input
  .rd_en          (rdata_req   ),
  .rd_data        (pic_data    ),  // output [15:0]
  .rd_empty       (            ),  // output
  .rd_water_level (            ),  // output
  .almost_empty   (            )   // output
);

wr_fifo u_wr_fifo  (
  .wr_clk         (wr_clk      ),    // input
  .wr_rst         (rst_n      ),    // input
  .wr_en          (datain_valid), 
  .wr_data        (datain      ),    //input [15:0]
  .wr_full        (            ),    // output
  .wr_water_level (            ),    // output
  .almost_full    (            ),    // output
  .rd_clk         (clk_100     ),    // input 
  .rd_rst         (rst_n      ),    // input
  .rd_en          (wfifo_rden  ),    // input
  .rd_data        (wfifo_dout  ),    // output [127:0]
  .rd_empty       (            ),    // output
  .rd_water_level (wfifo_rcount),    // output
  .almost_empty   (            )     // output
);
endmodule

下面展示一些 内联代码片

ddr3自加数测试模块
module ddr_test(
    input             clk_50m      /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/ ,   //时钟
    input             rst_n         ,   //复位,低有效
                                        
    output reg        wr_en        /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/ ,   //写使能
    output reg [15:0] wr_data       ,   //写数据
    output reg        rd_en        /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ,   //读使能
    input      [15:0] rd_data     /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ,   //读数据
    input      [27:0] data_max    /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ,   //写入ddr的最大数据量
    
    input             ddr3_init_done,   //ddr3初始化完成信号
    output reg        error_flag        //ddr3读写错误
    
    );

//reg define
reg        init_done_d0;
reg        init_done_d1;
reg [27:0] wr_cnt    /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ;   //写操作计数器
reg [27:0] rd_cnt     /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ;   //读操作计数器
reg        rd_valid  /* synthesis syn_preserve=1 */ /*synthesis PAP_MARK_DEBUG = "true"*/  ;   //读数据有效标志
reg [27:0] rd_cnt_d0   ;
  
//*****************************************************
//**                    main code
//***************************************************** 

//同步ddr3初始化完成信号
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0) begin
        init_done_d0 <= 1'b0 ;
        init_done_d1 <= 1'b0 ;
    end
    else begin
        init_done_d0 <= ddr3_init_done;
        init_done_d1 <= init_done_d0;
    end
end

//对读计数器做一拍延时使数据对齐
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0)
        rd_cnt_d0    <= 28'd0;
    else
        rd_cnt_d0 <= rd_cnt;
end 

//ddr3初始化完成之后,写操作计数器开始计数
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0) 
        wr_cnt <= 28'd0;
    else if(init_done_d1 && (wr_cnt < data_max ))
        wr_cnt <= wr_cnt + 1'b1;
    else 
       wr_cnt <= wr_cnt;
		//wr_cnt <= 28'd0;
end    

//ddr3写端口FIFO的写使能、写数据
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0) begin
        wr_en   <= 1'b0;
        wr_data <= 16'd0;
    end
    else if(wr_cnt >= 11'd0 && (wr_cnt < data_max )&&init_done_d1) begin
            wr_en   <= 1'b1;            //写使能拉高
            wr_data <= wr_cnt[15:0];    //写入数据
    end    
    else begin
            wr_en   <= 1'b0;
            wr_data <= 16'd0;
    end
end

//写入数据完成后,开始读操作
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0) 
        rd_en <= 1'b0;
    else if(wr_cnt >= data_max )         //写数据完成
        rd_en <= 1'b1;                   //读使能
    else
        rd_en <= rd_en;
end

//对读操作计数
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0) 
        rd_cnt <= 28'd0;
    else if(rd_en) begin
        if(rd_cnt < data_max - 1'd1)
            rd_cnt <= rd_cnt + 1'd1;
        else
            rd_cnt <= 28'd0;
    end
end

//第一次读取的数据无效,后续读操作所读取的数据才有效
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0) 
        rd_valid <= 1'b0;
    else if(rd_cnt >= data_max - 1'd1 )  //等待第一次读操作结束
        rd_valid <= 1'b1;                //后续读取的数据有效
    else
        rd_valid <= rd_valid;
end

//读数据有效时,若读取数据错误,给出标志信号
always @(posedge clk_50m ) begin
    if(rst_n == 1'd0)
        error_flag <= 1'b0; 
    else if(wr_en)       
        error_flag <= 1'b0;      
    else if(rd_valid && ((rd_data[15:0] != rd_cnt_d0[15:0])) )
        error_flag <= 1'b1;             //若读取的数据错误,将错误标志位拉高
    else
        error_flag <= error_flag;
end

endmodule
  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值