zoukankan      html  css  js  c++  java
  • FPGA基于ISE的DDR的各个端口介绍及写入数据的驱动(6)

              上一节已经成功地字节仿照DDR的官方例子,写出了自己的驱动,并且谢了下关的激励文件,接下来就主要介绍怎么样实现DDR的写数据操作,以及相关端口的介绍,首先根据我们的例子以及我们上一节自己写的仿真,对相关端口介绍一下。

               DDR IP中最核心的代码就是u_mig_39_2中的端口例化(这个名称是你在创建DDR IP时自己默认的,当然依然可以修改),其中的接口可以分为俩大部分,可以总结为以下的结构框图,方便理解和记忆(VISIO画图的时候字体选的6PT,有点模糊哈)。

          

     其中以下几个信号是提供给用户使用的,用户可以用这两个端口来设置DDR IP的参考时钟和复位信号,都是输入类型的信号(针对DDR来说)

    c3_sys_clk    :input  DDR3的参考时钟

    c3_sys_rst_i  :input DDR3的复位信号 

    c3_calib_done :当DDR的所有初始化信息完成后此信号拉高,才能对DDR惊醒相关的操作
    mcb3_rzq :硬件接电阻的端口
    mcb3_zio:硬件接电阻的端口

    命令路径端口及作用:

    c3_p0_cmd_clk //命令FIFO的用户时钟。 FIFO信号是 在这个时钟的上升沿捕获

    c3_p0_cmd_en //该高电平有效信号是用于写入的写入使能信号命令FIFO。
    c3_p0_cmd_instr  //当前指令的命令代码。 位0表示READ / WRITE选择,Bit 1为Auto预充电启用,位2代表刷新总是优先考虑 

    Write: 3'b000
    Read: 3'b001
    Write with Auto Precharge: 3'b010
    Read with Auto Precharge: 3'b011
    Refresh: 3'b1xx


    c3_p0_cmd_bl//当前用户字数的突发长度交易。 突发长度编码为0到63,代表1到64个用户词(例如,6'b00011 是一个突发长度4的交易)。 用户字宽等于端口宽度(例如,突发长度为3 64位端口传输3 x 64位用户字= 192位 总)。

    c3_p0_cmd_byte_addr/*当前事务的字节起始地址。地址必须与端口大小对齐: 32位端口:低两位必须为0。 64位端口:低三位必须为0。 128位端口:低4位必须为0*/

    c3_p0_cmd_empty /这个命令FIFO的高电平有效空标志 
    c3_p0_cmd_full/此高电平有效输出是命令的man标志l

    路径命令的时序:

    用户界面的命令路径使用简单的4深度FIFO结构来保存待定命令。 请求的指令类型,地址和突发长度事务全部加载到此命令FIFO中。 来自的完整标志(pX_cmd_full)信号命令FIFO必须为低电平才能将新命令接收到FIFO中在pX_cmd_clk的上升沿期间,pX_cmd_en被置位。 否则,命令是忽略。 图4-4和图4-5说明了加载命令的协议FIFO。

     写命令的端口及其作用:

    c3_p0_wr_clk ://该信号是写数据FIFO的用户时钟

    c3_p0_wr_en ://写数据使能,高有效,拉高的时候才能写入数据。8
    c3_p0_wr_mask://写数据的掩码, 8BIT大小,适合一个数据的字节关联的,决定了当前字节是否可以写入到MEMERY当中

    c3_p0_wr_data :写入要写入的数据值 数据FIFO并发送到内存。 PX_SIZE 可以是32位,64位或128位,具体取决于 端口配置

    c3_p0_wr_full ://高有效的满信号 

    c3_p0_wr_empty:/高有效的空信号

    c3_p0_wr_count ://用来表示当前写FIFO内部含有多少个数据
    c3_p0_wr_underrun://
    c3_p0_wr_error://可以当做一个状态输出

     写命令的时序:

    用户界面的写入路径使用简单的64深度FIFO结构来保存数据准备将事务写入内存。与命令FIFO类似,满标志写入数据FIFO中的(pX_wr_full)必须为低电平才能接受新数据在pX_wr_clk的上升沿期间pX_wr_en被置位时的FIFO。否则,数据被忽略了。如果满标志为低,则pX_wr_data总线在上升时被捕获到FIFO中,对于每一个PX_WR_EN有效的时候,PX_WR_DATA数据总线上必须有有效的数据。

     命令路径和写路径之间的协调:

          命令路径可以看成是一个命令 FIFO;写数据路径可以看成是一个写数据 FIFO。

            在执行写命令之前要确保Write data FIFO中是有数据的。方法:先向Write data FIFO中写入想要写入到DDR内部的数据,之后再向CMD FIFO中写入相应的命令。以确保在执行写命令之前,我的write data FIFO中已有数据

    可以得出以下时序图:

     其中Wr_trig是调试信号,

    接下来就是写代码了:

       (1)端口:包括写命令路径和写数据路径,还包括时钟、复位等信号。

     1 module    ddr_drive(                              
     2                                                   
     3      //systerm    signals                         
     4      input        wire          sclk           ,  
     5      input        wire          s_rst_n          ,
     6      //ddr interface                              
     7      output       reg           p0_wr_en       ,  
     8      output       wire          p0_cmd_en      ,  
     9      output       wire    [5:0] p0_cmd_bl      ,  
    10      output       wire    [2:0] p0_cmd_instr   ,  
    11      output       wire    [29:0]p0_cmd_addr    ,  
    12      output       reg     [63:0]p0_wr_data     ,  
    13      output       wire    [7:0] p0_wr_mask     ,  
    14      //debug signals                              
    15      input        wire          wr_trig           
    16                                                   
    17 );                                                

    (2)产生写使能信号:

    1 //p0_wr_en                                         
    2 always    @(posedge sclk or negedge s_rst_n)begin  
    3            if(!s_rst_n)                            
    4               p0_wr_en    <=      1'b0   ;         
    5            else if(p0_wr_data>=15)                 
    6               p0_wr_en   <=      1'b0  ;           
    7            else if (wr_trig == 1'b1)               
    8               p0_wr_en    <=      1'b1   ;            
    9 end                                                

    (3)产生要写入的数据

    1 //p0_wr_data                                              
    2 always   @(posedge sclk or negedge s_rst_n)begin          
    3              if(!s_rst_n)                                   
    4                 p0_wr_data     <=     'd0  ;                
    5              else if(p0_wr_en == 1'b1 )                     
    6                 p0_wr_data     <=    p0_wr_data   + 1'b1 ;  
    7                                                               
    8 end                                                       

    (4)配置写入的命令,就是配置相关DDR的突发长度等等

    1 assign       p0_cmd_bl     =      'd16                  ;       
    2 assign       p0_cmd_instr =    3'b000                  ;        
    3                                                                 
    4 assign       p0_cmd_en     = ~p0_wr_en & wr_en_neg     ;        
    5 assign       p0_cmd_addr   =      'd0                   ;       
    6 assign       p0_wr_mask   =      8'h0                 ;         

    (5)中间变量

    1 reg                        wr_en_neg           ;//negedge flag    
    2 //wr_en_neg.边沿检测                   
    3 always   @(posedge  sclk )begin        
    4           wr_en_neg  <=   p0_wr_en  ;  
    5                                        
    6 end                                    
    7                                        

    驱动和写入一个0-15的数据的小驱动就完成了

    (6)TB激励文件

      1 `timescale    1ps/1ps
      2 
      3 
      4 module      tb_ddr_top ;
      5 
      6 reg                                      ddr3_ref_clk         ;
      7 reg                                      ddr3_rst_n           ;
      8 //bebug   signals 
      9 reg                                      wr_trig              ;
     10 wire                                     c3_calib_done        ;
     11 
     12 //ddr3 interface 
     13 wire [15:0]                               mcb3_dram_dq        ;
     14 wire [12:0]                               mcb3_dram_a         ;
     15 wire [2:0]                                mcb3_dram_ba        ;
     16 wire                                      mcb3_dram_ras_n     ;
     17 wire                                      mcb3_dram_cas_n     ;
     18 wire                                      mcb3_dram_we_n      ;
     19 wire                                      mcb3_dram_odt       ;
     20 wire                                      mcb3_dram_reset_n   ;
     21 wire                                      mcb3_dram_cke       ;
     22 wire                                      mcb3_dram_dm        ;
     23 wire                                      mcb3_dram_udqs      ;
     24 wire                                      mcb3_dram_udqs_n    ;
     25 wire                                      mcb3_rzq            ;
     26 wire                                      mcb3_zio            ;
     27 wire                                      mcb3_dram_udm       ;
     28 wire                                      mcb3_dram_dqs       ;
     29 wire                                      mcb3_dram_dqs_n     ;
     30 wire                                      mcb3_dram_ck        ;
     31 wire                                      mcb3_dram_ck_n      ;
     32 
     33 
     34 
     35 
     36 parameter C3_MEMCLK_PERIOD     = 3200;
     37 
     38 
     39 initial    begin
     40     
     41         ddr3_ref_clk     =     1;
     42         ddr3_rst_n       =     0;
     43         #20000;
     44         ddr3_rst_n       =     1;    
     45     
     46     
     47 end 
     48 
     49 
     50 
     51 
     52 //produce debug  signals 
     53 initial    begin
     54           wr_trig      <=     0;
     55           @(posedge c3_calib_done)
     56           #100000
     57           wr_trig      <=     1;
     58           #25600
     59           wr_trig      <=     0;
     60 end 
     61 
     62 
     63 
     64 
     65 always   #(C3_MEMCLK_PERIOD/2)  ddr3_ref_clk     =     ~ddr3_ref_clk ;
     66 
     67 
     68  ddr_top   ddr_top_inst(
     69 
     70    
     71    
     72    //sysyterm  interface
     73    .c3_sys_clk                               (ddr3_ref_clk       ),  
     74    .c3_sys_rst_i                             (ddr3_rst_n         ), 
     75    //ddr3 interface 
     76    .mcb3_dram_dq                             (mcb3_dram_dq       ),
     77    .mcb3_dram_a                              (mcb3_dram_a        ),
     78    .mcb3_dram_ba                             (mcb3_dram_ba       ),
     79    .mcb3_dram_ras_n                          (mcb3_dram_ras_n    ),
     80    .mcb3_dram_cas_n                          (mcb3_dram_cas_n    ),
     81    .mcb3_dram_we_n                           (mcb3_dram_we_n     ),
     82    .mcb3_dram_odt                            (mcb3_dram_odt      ),
     83    .mcb3_dram_reset_n                        (mcb3_dram_reset_n  ),
     84    .mcb3_dram_cke                            (mcb3_dram_cke      ),
     85    .mcb3_dram_dm                             (mcb3_dram_dm       ),
     86    .mcb3_dram_udqs                           (mcb3_dram_udqs     ),
     87    .mcb3_dram_udqs_n                         (mcb3_dram_udqs_n   ),
     88    .mcb3_rzq                                 (mcb3_rzq           ),
     89    .mcb3_zio                                 (mcb3_zio           ),
     90    .mcb3_dram_udm                            (mcb3_dram_udm      ),
     91    .mcb3_dram_dqs                            (mcb3_dram_dqs      ),
     92    .mcb3_dram_dqs_n                          (mcb3_dram_dqs_n    ),
     93    .mcb3_dram_ck                             (mcb3_dram_ck       ),
     94    .mcb3_dram_ck_n                           (mcb3_dram_ck_n     ),
     95    //debug   signals 
     96    .wr_trig                                   (wr_trig)          ,
     97    .c3_calib_done                            (c3_calib_done)
     98 
     99 );
    100 
    101  ddr3_model_c3 u_mem_c3(                             
    102   .ck         (mcb3_dram_ck),                        
    103   .ck_n       (mcb3_dram_ck_n),                      
    104   .cke        (mcb3_dram_cke),                       
    105   .cs_n       (1'b0),                                
    106   .ras_n      (mcb3_dram_ras_n),                     
    107   .cas_n      (mcb3_dram_cas_n),                  
    108   .we_n       (mcb3_dram_we_n),                      
    109   .dm_tdqs    ({mcb3_dram_udm,mcb3_dram_dm}),        
    110   .ba         (mcb3_dram_ba),                        
    111   .addr       (mcb3_dram_a),                         
    112   .dq         (mcb3_dram_dq),                        
    113   .dqs        ({mcb3_dram_udqs,mcb3_dram_dqs}),      
    114   .dqs_n      ({mcb3_dram_udqs_n,mcb3_dram_dqs_n}),  
    115   .tdqs_n     (),                                    
    116   .odt        (mcb3_dram_odt),                       
    117   .rst_n      (mcb3_dram_reset_n)                    
    118   ); 
    119   
    120 // The PULLDOWN component is connected to the ZIO signal primarily to avoid the    
    121 // unknown state in simulation. In real hardware, ZIO should be a no connect(NC) pin. 
    122    PULLDOWN zio_pulldown3 (.O(zio3));   PULLDOWN rzq_pulldown3 (.O(rzq3));            
    123                                                                                       
    124 
    125   
    126      endmodule                                                 

     (7)例化到顶层

    
    

    module ddr_top(

    
    



    //sysyterm interface
    input c3_sys_clk ,
    input c3_sys_rst_i ,
    //ddr3 interface
    inout [15:0] mcb3_dram_dq ,
    output wire [12:0] mcb3_dram_a ,
    output wire [2:0] mcb3_dram_ba ,
    output wire mcb3_dram_ras_n ,
    output wire mcb3_dram_cas_n ,
    output wire mcb3_dram_we_n ,
    output wire mcb3_dram_odt ,
    output wire mcb3_dram_reset_n ,
    output wire mcb3_dram_cke ,
    output wire mcb3_dram_dm ,
    inout mcb3_dram_udqs ,
    inout mcb3_dram_udqs_n ,
    inout mcb3_rzq ,
    inout mcb3_zio ,
    output wire mcb3_dram_udm ,
    inout mcb3_dram_dqs ,
    inout mcb3_dram_dqs_n ,
    output wire mcb3_dram_ck ,
    output wire mcb3_dram_ck_n ,
    //debug
    input wire wr_trig ,
    input wire c3_calib_done

    
    

    );

    
    

    /*********************************************************************
    *************************signals define********************************
    **********************************************************************/



    //ddr interface (write modle )
    wire p0_wr_en ;
    wire p0_cmd_en ;
    wire [5:0] p0_cmd_bl ;
    wire [2:0] p0_cmd_instr ;
    wire [29:0]p0_cmd_addr ;
    wire [63:0]p0_wr_data ;
    wire [7:0] p0_wr_mask ;

    
    
    
    
    
    
    
    

    /*********************************************************************
    ****************************main code ********************************
    **********************************************************************/
    ddr_drive ddr_drive_inst(

    
    

    //systerm signals
    .sclk (c3_clk0 ),
    .s_rst_n (~c3_rst0 ),
    //ddr interface
    .p0_wr_en (p0_wr_en ),
    .p0_cmd_en (p0_cmd_en ),
    .p0_cmd_bl (p0_cmd_bl ),
    .p0_cmd_instr (p0_cmd_instr),
    .p0_cmd_addr (p0_cmd_addr ),
    .p0_wr_data (p0_wr_data ),
    .p0_wr_mask (p0_wr_mask ),
    //debug signals
    .wr_trig (wr_trig )

    );

    
    
    
    
    
    
    
    

    mig_39_2 # (
    .C3_P0_MASK_SIZE(8),
    .C3_P0_DATA_PORT_SIZE(64),
    .C3_P1_MASK_SIZE(8),
    .C3_P1_DATA_PORT_SIZE(64),
    .DEBUG_EN(0),
    .C3_MEMCLK_PERIOD(3200),//当前的时钟周期
    .C3_CALIB_SOFT_IP("TRUE"),
    .C3_SIMULATION("TRUE"),//仿真
    .C3_RST_ACT_LOW(1),//复位信号的配置
    .C3_INPUT_CLK_TYPE("SINGLE_ENDED"),//时钟模式
    .C3_MEM_ADDR_ORDER("BANK_ROW_COLUMN"),//内存读取的顺序模式
    .C3_NUM_DQ_PINS(16),
    .C3_MEM_ADDR_WIDTH(13),
    .C3_MEM_BANKADDR_WIDTH(3)
    )
    u_mig_39_2 (
    //DDR3 的接口
    .c3_sys_clk (c3_sys_clk), //input DDR3的参考时钟
    .c3_sys_rst_i (c3_sys_rst_i), //input DDR3的复位信号

    
    

    .mcb3_dram_dq (mcb3_dram_dq),
    .mcb3_dram_a (mcb3_dram_a),
    .mcb3_dram_ba (mcb3_dram_ba),
    .mcb3_dram_ras_n (mcb3_dram_ras_n),
    .mcb3_dram_cas_n (mcb3_dram_cas_n),
    .mcb3_dram_we_n (mcb3_dram_we_n),
    .mcb3_dram_odt (mcb3_dram_odt),
    .mcb3_dram_cke (mcb3_dram_cke),
    .mcb3_dram_ck (mcb3_dram_ck),
    .mcb3_dram_ck_n (mcb3_dram_ck_n),
    .mcb3_dram_dqs (mcb3_dram_dqs),
    .mcb3_dram_dqs_n (mcb3_dram_dqs_n),
    .mcb3_dram_udqs (mcb3_dram_udqs), // for X16 parts
    .mcb3_dram_udqs_n (mcb3_dram_udqs_n), // for X16 parts
    .mcb3_dram_udm (mcb3_dram_udm), // for X16 parts
    .mcb3_dram_dm (mcb3_dram_dm),
    .mcb3_dram_reset_n (mcb3_dram_reset_n),




    //sppourt for user
    .c3_clk0 (c3_clk0),//output 输出给用户提供的
    .c3_rst0 (c3_rst0),//output 输出给用户提供的

    
    

    .c3_calib_done (c3_calib_done),
    .mcb3_rzq ( mcb3_rzq ),
    .mcb3_zio (mcb3_zio ),

    //P0,p1表示两个用户会接口
    /*********************command path****************************/
    .c3_p0_cmd_clk (c3_clk0 ), //命令FIFO的用户时钟。 FIFO信号是 在这个时钟的上升沿捕获。
    .c3_p0_cmd_en (p0_cmd_en), //该高电平有效信号是用于写入的写入使能信号命令FIFO。
    .c3_p0_cmd_instr (p0_cmd_instr), //当前指令的命令代码。 位0表示READ / WRITE选择,Bit 1为Auto预充电启用,位2代表刷新总是优先考虑
    .c3_p0_cmd_bl (p0_cmd_bl), //当前用户字数的突发长度交易。 突发长度编码为0到63,代表1到64个用户词(例如,6'b00011 是一个突发长度4的交易)。 用户字宽等于端口宽度(例如,突发长度为3 64位端口传输3 x 64位用户字= 192位 总)。
    /*当前事务的字节起始地址。地址
    必须与端口大小对齐:
    32位端口:低两位必须为0。
    64位端口:低三位必须为0。
    128位端口:低4位必须为0*/
    .c3_p0_cmd_byte_addr (p0_cmd_addr),
    .c3_p0_cmd_empty ( ), //这个命令FIFO的高电平有效空标志
    .c3_p0_cmd_full ( ), //此高电平有效输出是命令的man标志

    /*********************write cmd****************************/
    .c3_p0_wr_clk (c3_clk0 ),//该信号是写数据FIFO的用户时钟
    /*该高电平有效信号是写使能
    用于写数据FIFO。它表明了
    pX_wr_data上的值有效
    加载到FIFO。数据已加载
    pX_wr_clk的上升沿时
    pX_wr_en = 1且pX_wr_full = 0。*/
    .c3_p0_wr_en (p0_wr_en),
    .c3_p0_wr_mask (p0_wr_mask),//写数据的掩码,
    /*写入要写入的数据值
    数据FIFO并发送到内存。 PX_SIZE
    可以是32位,64位或128位,具体取决于
    端口配置*/
    .c3_p0_wr_data (p0_wr_data),
    .c3_p0_wr_full ( ), //高有效的满信号
    .c3_p0_wr_empty ( ),//高有效的空信号
    /*写入数据FIFO的计数值。这个
    输出表示有多少用户单词
    在FIFO中(从1到64)。计数值为
    0表示FIFO为空。这个信号
    延迟的延迟比
    pX_wr_empty标志。因此,FIFO
    可能是空的或经历不足
    即使计数不为0。*/
    .c3_p0_wr_count ( ),
    .c3_p0_wr_underrun ( ),//高电平有效,欠载标志。
    .c3_p0_wr_error ( ),
    /*********************read cmd****************************/
    .c3_p0_rd_clk (c3_p0_rd_clk ),//该信号是du数据FIFO的用户时钟
    .c3_p0_rd_en (c3_p0_rd_en ),
    .c3_p0_rd_data (c3_p0_rd_data ),
    .c3_p0_rd_full (c3_p0_rd_full ),
    .c3_p0_rd_empty (c3_p0_rd_empty),
    .c3_p0_rd_count (c3_p0_rd_count),
    .c3_p0_rd_overflow (c3_p0_rd_overflow),
    .c3_p0_rd_error (c3_p0_rd_error ),
    /********************P1 user port************************/
    .c3_p1_cmd_clk (c3_p1_cmd_clk ),
    .c3_p1_cmd_en (c3_p1_cmd_en ),
    .c3_p1_cmd_instr (c3_p1_cmd_instr ),
    .c3_p1_cmd_bl (c3_p1_cmd_bl ),
    .c3_p1_cmd_byte_addr (c3_p1_cmd_byte_addr),
    .c3_p1_cmd_empty (c3_p1_cmd_empty ),
    .c3_p1_cmd_full (c3_p1_cmd_full ),
    .c3_p1_wr_clk (c3_p1_wr_clk),
    .c3_p1_wr_en (c3_p1_wr_en),
    .c3_p1_wr_mask (c3_p1_wr_mask),
    .c3_p1_wr_data (c3_p1_wr_data),
    .c3_p1_wr_full (c3_p1_wr_full),
    .c3_p1_wr_empty (c3_p1_wr_empty),
    .c3_p1_wr_count (c3_p1_wr_count),
    .c3_p1_wr_underrun (c3_p1_wr_underrun),
    .c3_p1_wr_error (c3_p1_wr_error),
    .c3_p1_rd_clk (c3_p1_rd_clk),
    .c3_p1_rd_en (c3_p1_rd_en),
    .c3_p1_rd_data (c3_p1_rd_data),
    .c3_p1_rd_full (c3_p1_rd_full),
    .c3_p1_rd_empty (c3_p1_rd_empty),
    .c3_p1_rd_count (c3_p1_rd_count),
    .c3_p1_rd_overflow (c3_p1_rd_overflow),
    .c3_p1_rd_error (c3_p1_rd_error)
    );

    
    


    endmodule

  • 相关阅读:
    windows xp查看缩略图时有缩略图没有文件名
    数据库的相关操作
    使用timer控件创建一个简单的报警程序
    xp_sendmail的正确配置与使用
    SQL Server 索引结构及其使用(三)
    启动与关闭服务器
    不间断连续图片滚动效果的制作方法
    使用C#调用外部Ping命令获取网络连接情况
    SQL Server 索引结构及其使用(一)
    winform 与asp.net 下拉列表的区别
  • 原文地址:https://www.cnblogs.com/lgy-gdeu/p/11515632.html
Copyright © 2011-2022 走看看