【实战经验】--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.使用

  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

            

 

猜你喜欢

转载自www.cnblogs.com/yjw951012/p/10998521.html
今日推荐