【實戰經驗】--Xilinx--IPcore--MCB(DDR3)運用


1.背景與介紹

  1)在導師安排的新的任務中,用到了一塊2G大小的DDR3(MT41K128M16JT-107)。本打算像之前用SDRAM一樣自己寫初始化,讀寫模塊,但是師兄跟我說可以用Xilinx自帶的MCB來進行控制,會方便很多,於是自己在網上找了一些資料,摸索了一番,然后在實際運用后,寫下了這篇隨筆。

  2)我們先看MCB內部結構圖,重點關注兩個部分User Logic 與PHY。

    PHY是外部IO接口,也就是和DDR3直接連接的接口;

    User Logic 對應的部分則是需要我用戶編寫的部分,從圖中可以看出:用戶只需控制CMD與數據即可,而這里的CMD也不復雜,Xilinx將其做的十分簡單,用戶只需發送對應的讀、寫、帶刷新寫、帶刷新讀即可,相對來說使用還是很簡單的。 

 

 2.生成IP核

  1)如何產生IP核的過程就不說了,記住叫Memory Interface Generator就行,直接進入設置部分。

  2)選擇兼容平台,根據用戶自己需求選擇,我這里無需其他拓展,因此都沒選擇。

  3)選擇bank區域,根據用戶數據手冊上的介紹,優先選擇左側/左下側。(用戶數據在點擊圖中左下區域后可以得到)

  4)選擇DDR3的芯片型號,如果沒有,可以自己定義一塊,不過需要注意的是要選擇接口相似的芯片作為模板。

  5)定義自己的芯片,我的芯片是MT41K128M16JT-107 ,其中128M16代表128Meg*16,-107表示速度在芯片數據手冊種得知可以向后兼容(-125、-15E、-187E)因此選擇MT41J128M16XX-125,這樣需要改動的東西就非常少了。

先附上我使用的芯片的部分參數

    

    

 

再附上我定義的芯片,可見幾乎沒有改動。

 6)此處無需改動,保留默認值即可。

 7)此處有幾種選擇,我選擇是128bit,既一次寫入/讀取128bit數據,具體如何設置,可以查看用戶手冊ug388.pdf。

 8)此處設置終端補償電阻PIN腳(保持默認或者看自己板上怎么連接的),單時鍾輸入。

 9)最后一路NEXT到底,點擊Generate,一個MCB的IP核就生成了。

10)IP核生成后,我們會在其目錄下看見三個文件夾,其中內容如圖所示。

11)我們打開user_design文件夾,其中par與rtl最為重要,par中包含UCF文件,這會讓我們定義端口容易很多,而rtl則包含設計的.v文件

 

3.使用

  0)首先自然是要生成相應的時鍾 333MHz!!!

  1)將生成的MCB移出(右鍵--remove),再將uesr_design中rtl下文件手動添加至工程中(右鍵--add source)。(為的是使用PLL生成的時鍾)

  2)修改memc3_infrastructure_inst 中的時鍾

      先注釋掉這一部分(這是MCB生成時鍾的部分)

          將這里的時鍾換成sys_clk(原來是sys_clk_ibufg)

  3)接下來我們來了解一下MCB DDR3的接口 ,接口的說明也在下面這段代碼中;

 1 MCB_TEST # (
 2     .C3_P0_MASK_SIZE(16),
 3     .C3_P0_DATA_PORT_SIZE(128),
 4     .DEBUG_EN(0),
 5     .C3_MEMCLK_PERIOD(3000),        //change
 6     .C3_CALIB_SOFT_IP("TRUE"),
 7     .C3_SIMULATION("FALSE"),
 8     .C3_RST_ACT_LOW(0),
 9     .C3_INPUT_CLK_TYPE("SINGLE_ENDED"),
10     .C3_MEM_ADDR_ORDER("ROW_BANK_COLUMN"),
11     .C3_NUM_DQ_PINS(16),
12     .C3_MEM_ADDR_WIDTH(15),
13     .C3_MEM_BANKADDR_WIDTH(3)
14 )
15 u_MCB_MIG (
16    .c3_sys_clk             (clk_ddr3_sys),        //DDR3時鍾333MHz對應3000ps 
17    .c3_sys_rst_i           (rst_ddr3_sys),      //復位信號 高有效
18 //物理接口,不用管 
19    .mcb3_dram_dq           (mcb3_dram_dq),      //讀寫數據 
20    .mcb3_dram_a            (mcb3_dram_a),          //讀寫地址 
21    .mcb3_dram_ba           (mcb3_dram_ba),        //bank選擇 
22    .mcb3_dram_ras_n        (mcb3_dram_ras_n),   //行使能 低有效                   
23    .mcb3_dram_cas_n        (mcb3_dram_cas_n),   //列使能 低有效          
24    .mcb3_dram_we_n         (mcb3_dram_we_n),    //使能 低有效             
25    .mcb3_dram_odt          (mcb3_dram_odt),        //PHYIO 
26    .mcb3_dram_cke          (mcb3_dram_cke),      //PHYIO                        
27    .mcb3_dram_ck           (mcb3_dram_ck),      //PHYIO                        
28    .mcb3_dram_ck_n         (mcb3_dram_ck_n),      //PHYIO     
29    .mcb3_dram_dqs          (mcb3_dram_dqs),     //PHYIO                         
30    .mcb3_dram_dqs_n        (mcb3_dram_dqs_n),    //PHYIO
31    .mcb3_dram_udqs         (mcb3_dram_udqs),    // for X16 parts                        
32    .mcb3_dram_udqs_n       (mcb3_dram_udqs_n),  // for X16 parts
33    .mcb3_dram_udm          (mcb3_dram_udm),     // for X16 parts
34    .mcb3_dram_dm           (mcb3_dram_dm),        //PHYIO
35    .mcb3_dram_reset_n      (mcb3_dram_reset_n),    //PHYIO
36    .c3_clk0                    (c3_clk0),          //PHYIO
37    .c3_rst0                    (c3_rst0),          //PHYIO
38     .c3_calib_done          (c3_calib_done),        //goes High to indicate that calibration has completed
39    .mcb3_rzq               (mcb3_rzq),  
40    .mcb3_zio               (mcb3_zio),
41     
42     //command path signals
43    .c3_p0_cmd_clk          (clk_ddr3),          //用戶讀寫MCB內部FIFO時鍾 
44    .c3_p0_cmd_en           (mcb3_cmd_en),       //high signal is the write-enable signal for command fifo
45    .c3_p0_cmd_instr        (mcb3_cmd_instr),    //CMD
46    .c3_p0_cmd_bl           (mcb3_cmd_bl),       //突發長度,大小為0-63,代表1-64的突發長度(即連續讀/寫多少次) (for example, 6'b00011 is a burst length 4 transaction). The user word width equals the port width (for example, a burst length of 3 on a 64-bit port transfers 3 x 64-bit user words = 192 bits total).
47    .c3_p0_cmd_byte_addr    (mcb3_cmd_byte_addr),//MCB的讀寫地址,寫的時候等於寫地址,讀的時候等於讀地址 
48    .c3_p0_cmd_empty        (mcb3_cmd_empty),    //MCB空 
49    .c3_p0_cmd_full         (mcb3_cmd_full),     //MCB滿 
50     //write datapath
51    .c3_p0_wr_clk           (clk_ddr3),          //等於上面的時鍾; 
52    .c3_p0_wr_en            (mcb3_wr_en),        //Data is loaded on the rising edge of pX_wr_clk when pX_wr_en = 1 and pX_wr_full = 0.
53    .c3_p0_wr_mask          (mcb3_wr_mask),        //when a mask bit is high, the corresponding bte of data is masked.
54    .c3_p0_wr_data          (mcb3_wr_data),        //write data, size can be 32,64,128 bits, depending on port configuration. 
55    .c3_p0_wr_full          (mcb3_wr_full),
56    .c3_p0_wr_empty         (mcb3_wr_empty),
57    .c3_p0_wr_count         (mcb3_wr_count),        //output indicates how many user words are in the FIFO(0-64)0 means fifo empty 
58    .c3_p0_wr_underrun      (mcb3_wr_underrun),    //indicates there was not enough data in write data fifo to complete the transacion.
59    .c3_p0_wr_error         (mcb3_wr_error),        
60    //read datapath
61     .c3_p0_rd_clk           (clk_ddr3),                
62    .c3_p0_rd_en            (mcb3_rd_en),
63    .c3_p0_rd_data          (mcb3_rd_data),
64    .c3_p0_rd_full          (mcb3_rd_full),
65    .c3_p0_rd_empty         (mcb3_rd_empty),
66    .c3_p0_rd_count         (mcb3_rd_count),
67    .c3_p0_rd_overflow      (mcb3_rd_overflow),
68    .c3_p0_rd_error         (mcb3_rd_error)
69 );
MCB_接口

     從上面的注釋可以看出,和用戶編寫讀寫程序緊密相關的是下面這些接口:

      1*命令相關

        //command path signals

           .c3_p0_cmd_clk          (clk_ddr3),
           .c3_p0_cmd_en           (mcb3_cmd_en),
           .c3_p0_cmd_instr        (mcb3_cmd_instr), 
           .c3_p0_cmd_bl           (mcb3_cmd_bl),   
           .c3_p0_cmd_byte_addr    (mcb3_cmd_byte_addr),
           .c3_p0_cmd_empty        (mcb3_cmd_empty),
           .c3_p0_cmd_full         (mcb3_cmd_full),

          以en、instr、byte_addr為主,當進行讀寫操作時,這三個要同時變化;
       2*讀寫相關

        //write datapath
           .c3_p0_wr_clk           (clk_ddr3),  
           .c3_p0_wr_en            (mcb3_wr_en), 
           .c3_p0_wr_mask          (mcb3_wr_mask), 
           .c3_p0_wr_data          (mcb3_wr_data), 
           .c3_p0_wr_full          (mcb3_wr_full),
           .c3_p0_wr_empty         (mcb3_wr_empty),
           .c3_p0_wr_count         (mcb3_wr_count), 
           .c3_p0_wr_underrun      (mcb3_wr_underrun), 
           .c3_p0_wr_error         (mcb3_wr_error),  
         //read datapath
           .c3_p0_rd_clk           (clk_ddr3),    
           .c3_p0_rd_en            (mcb3_rd_en),
           .c3_p0_rd_data          (mcb3_rd_data),
           .c3_p0_rd_full          (mcb3_rd_full),
           .c3_p0_rd_empty         (mcb3_rd_empty),
           .c3_p0_rd_count         (mcb3_rd_count),
           .c3_p0_rd_overflow      (mcb3_rd_overflow),
           .c3_p0_rd_error         (mcb3_rd_error)

          以en、data、full為主;

  4)簡單舉例:

     1*先說指令

       localparam    MCB_CMD_WR    = 3'b000; //mcb write cmd
       localparam    MCB_CMD_RD    = 3'b001; //mcb read cmd
       localparam    MCB_CMD_WP    = 3'b010; //mcb write with auto precharge cmd
       localparam    MCB_CMD_RP    = 3'b011; //mcb read with auto precharge cmd
       localparam    MCB_CMD_RF    = 3'b100; //mcb refresh cmd

     2*簡單舉例(以寫為例,代碼不全,領會思路)

 1 //先將數據存入MCB的FIFO中;
 2     if(cnt_fifo_rd>=7'd64) begin   //write 64 at one time 1KB
 3         cnt_fifo_rd <= cnt_fifo_rd;
 4         ad_fifo_rd_en_r <= 1'b0;    //去讀本地fifo中的數據
 5         end
 6     else begin
 7         cnt_fifo_rd <= cnt_fifo_rd + 1'b1;
 8         ad_fifo_rd_en_r <= 1'b1;
 9     end
10 assign mcb3_wr_en = ad_fifo_rd_en_r;  //實際上要延遲一個時鍾,這里做演示就不延遲了。
11 assign mcb3_wr_data = ad_fifo_rd_data;  //同時傳數據
12 //產生寫命令的請求
13     if(!rst_n)
14         u_wr_cmd_en <= 1'b0;
15     else if(u_wr_cmd_done)                //檢測到指令發送完成,清除標志信號?
16           u_wr_cmd_en <= 1'b0; //clear 
17     else if(cnt_fifo_rd==7'd63)            //寫入63次后產生寫命令請求(提前一個產生,等存夠64次后剛好產生寫請求
18         u_wr_cmd_en <= 1'b1; //enable
19     else
20           u_wr_cmd_en <= u_wr_cmd_en;
21 end
22 //檢測到寫命令請求,發出寫指令
23   if(u_wr_cmd_en) begin //write 
24         mcb3_cmd_instr_r     <= MCB_CMD_WP;
25         mcb3_cmd_byte_addr_r <= u_wr_addr;
26         mcb3_cmd_bl_r      <= mcb3_wr_bl; 
27     mcb3_cmd_wr_p      <= 1'b1;
28     mcb3_cmd_rd_p      <= 1'b0;
29   end
30   assign u_wr_cmd_done0 = mcb3_cmd_en&(mcb3_cmd_instr== MCB_CMD_WP);    // 用戶寫指令發送完成,產生標志信號
MCB_WR_EXAMPLE

 


免責聲明!

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



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