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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM