Xilinx DDR3 MIG系列——ddr3控制器的时钟架构

本文深入探讨了Xilinx DDR3 MIG控制器的时钟架构,包括PLL和MMCM的使用。PLL输入时钟有多种选择,输出时钟用于内部逻辑和I/O。MMCM1和MMCM2的输入输出时钟配置详细解析,强调了时钟同步和占空比的重要性。同时,文中指出了Vivado的显示bug和工程移植时的注意事项。
摘要由CSDN通过智能技术生成

本节目录

一、ddr3控制器的时钟架构
1、PLL输入时钟——系统时钟system_clk
2、PLL输出时钟——sync_pulse、mem_refclk、freq_refclk、MMCM1的输入时钟
3、MMCM1的输入时钟和输出时钟
4、MMCM2的输入时钟和输出时钟

一、ddr3控制器的时钟架构
对于FPGA开发来说,调用IP或者移植功能模块时,首先了解的模块的时钟架构。
如何设计时钟架构至关重要,其次对于一些优秀的设计思路可以借鉴参考。
根据ug586_7Series_MIS,我们可以了解下大体上所有的时钟架构,手册提供了具体的时钟设计方式。之后,会对每个时钟进行分析,用于了解对应时钟的功能,以及用途。
从时钟图中可以看出来,PHY设计使用了一个PLL和两个MMCM(其中对应的MMCM1,需要与PLL在同一个Bank,用于补偿插入延迟)。
在这里插入图片描述通过位置约束将PLL与MMCM1固定在同一个Bank,此种方法可用于解决时序优化,通过固定位置约束,通过布线保证两路时钟shew几乎一致。
在这里插入图片描述
1、PLL输入时钟——系统时钟system_clk
IP生成界面中对应位置,共有三种选择差分Differential,单端Single-Ended,以及No buffer。
选择差分和单端,都会消耗bufg,如果在顶层输入的时钟,已经经过bufg,此处使用No buffer,可以节省一个bufg资源。
此处需要注意的是:选择输入时钟频率需要与硬件设计一致,本系列课程使用的是单端时钟200M,配置如下,
还有一个小bug,是vivado的显示bug,并不会保存我们设置的Input Clock period。
对于移植别人工程时,需要留意这一点,用两种方式,第一种可以与硬件确认提供的时钟,但是一般这种都是fpga开发者在顶层通过PLL生成的200m时钟 ,另一种方式可以通过旧工程的MIG IP的xdc约束文件去确认下。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
具体看看代码生成模块中,我们看看是怎么对应的?
在mig_7series_v4_2_clk_ibuf.v模块中,通过参数化SYSCKL_TYPE和generate if功能块实现对不同配置的设置。
这种方式值得借鉴,用于工程中可以兼容不同的设计。从下面的代码中,只有no buffer不会占用时钟资源。
在这里插入图片描述
2、PLL输出时钟——sync_pulse、mem_refclk、freq_refclk、MMCM1的输入时钟
PLL输出用途主要有四个:生成用于内部(FPGA)逻辑的时钟、生成用于写路径(输出)I/O逻辑的时钟、生成用于读取路径(输入)和延迟I/O逻辑的时钟、生成用于IDELAY参考时钟的时钟。
注意:参数最终生效的最顶层的,通过一层一层传递的至底层模块。

//***************************************************************************
   // The following parameters are multiplier and divisor factors for PLLE2.
   // Based on the selected design frequency these parameters vary.
   //***************************************************************************
   parameter CLKIN_PERIOD          = 5000,                                  // Input Clock Period
   parameter CLKFBOUT_MULT         = 8,                                     // write PLL VCO multiplier
   parameter DIVCLK_DIVIDE         = 1,                                     // write PLL VCO divisor
   parameter CLKOUT0_PHASE         = 337.5,                                 // Phase for PLL output clock (CLKOUT0)
   parameter CLKOUT0_DIVIDE        = 2,                                     // VCO output divisor for PLL output clock (CLKOUT0)
   parameter CLKOUT1_DIVIDE        = 2,                                     // VCO output divisor for PLL output clock (CLKOUT1)
   parameter CLKOUT2_DIVIDE        = 32,                                    // VCO output divisor for PLL output clock (CLKOUT2)
   parameter CLKOUT3_DIVIDE        = 8,                                     // VCO output divisor for PLL output clock (CLKOUT3)
   parameter MMCM_VCO              = 800,                                   // Max Freq (MHz) of MMCM VCO
   parameter MMCM_MULT_F           = 4,                                     // write MMCM VCO multiplier
   parameter MMCM_DIVCLK_DIVIDE    = 1,                                     // write MMCM VCO divisor

在这里插入图片描述
(1)sync_pulse
手册要求:sync_pulse必须为mem_refclk频率的1/16,且占空比必须为1/16或6.25%。
PLLE2_ADV的CLK_OUT2为同步脉冲,输入时钟为5000ps=5ns,即200M

  localparam real CLKIN1_PERIOD_NS = CLKIN_PERIOD / 1000.0;
  localparam CLKOUT4_DIVIDE = 2 * CLKOUT1_DIVIDE;
  localparam integer VCO_PERIOD
             = (CLKIN1_PERIOD_NS * DIVCLK_DIVIDE * 1000) / CLKFBOUT_MULT;
  localparam CLKOUT0_PERIOD = VCO_PERIOD * CLKOUT0_DIVIDE;
  localparam CLKOUT1_PERIOD = VCO_PERIOD * CLKOUT1_DIVIDE;
  localparam CLKOUT2_PERIOD = VCO_PERIOD * CLKOUT2_DIVIDE;
  localparam CLKOUT3_PERIOD = VCO_PERIOD * CLKOUT3_DIVIDE;
  localparam CLKOUT4_PERIOD = VCO_PERIOD * CLKOUT4_DIVIDE;
  localparam CLKOUT4_PHASE  = (SIMULATION == "TRUE") ? 22.5 : 168.75;
  localparam real CLKOUT3_PERIOD_NS = CLKOUT3_PERIOD / 1000.0;
  localparam real CLKOUT4_PERIOD_NS = CLKOUT4_PERIOD / 1000.0;

VCO_PERIOD=(CLKIN1_PERIOD_NS * DIVCLK_DIVIDE * 1000) / CLKFBOUT_MULT
=(5000/100011000)/8=625ps
sync_pulse的时钟周期:CLKOUT2_PERIOD = VCO_PERIOD * CLKOUT2_DIVIDE=62532=20000ps=20ns
mem_refclk的时钟周期:CLKOUT1_PERIOD = VCO_PERIOD * CLKOUT1_DIVIDE=625
2=1250ps
sync_pulse的时钟频率是mem_refclk的1/16,仿真图结果观察下,确实如此,总周期为1250ps+18750ps=20ns,占空比为1250ps/20000ps=1/16。
在这里插入图片描述
(2)mem_refclk的时钟周期为1250ps,时钟频率为800M
此处对应800M的是Clock Period
在这里插入图片描述
(3)freq_refclk的时钟周期为79ps+1171ps=1250ps,时钟频率为800M
(4)pll_clk3_out的时钟周期为1250ps+3671ps+79ps=5000ps,时钟频率为200M,主要是用于MMCM1的输入。
在这里插入图片描述
3、MMCM1的输入时钟和输出时钟
(1)MMCM1的输入时钟来自于pll_clk3,即200M时钟
(2)用于FPGA内部的输出时钟为clk,即图上PHY_Clk,来自于MMCM1的CLKFBOUT。
(3)MMCM Phase shift clok为mmcm_ps_clk=1250ps+3671ps+79ps+1171ps+3829ps=10ns
4、MMCM2的输入时钟和输出时钟
MMCM2的输入时钟,也可通过UI界面进行配置。
同样此处也会出现bug,选择设置使用系统时钟。
在这里插入图片描述在这里插入图片描述在这里插入图片描述
代码功能实现在mig_7series_v4_2_iodelay_ctrl.v模块中,主要涉及到IDELAYCTRL,因此需要引入参考时钟。
手册中介绍:对于DDR3的设计,IDELAY参考时钟的生成需要一个MMCM2。如果设计频率为> 667 MHz,则IDELAY参考时钟为300 MHz或400MHz(取决于FPGA速度等级)。MIG实例化了一个MMCM2,用于300 MHz和400 MHz的时钟生成。

##                    FPGA Family:       ZYNQ
##                    FPGA Part:         XC7Z100-FFG900
##                    Speedgrade:        -2
##                    Design Entry:      VERILOG
##                    Frequency:         800 MHz
##                    Time Period:       1250 ps  
   parameter STARVE_LIMIT          = 2,                                    // # = 2,3,4.
   parameter REF_CLK_MMCM_IODELAY_CTRL    = "TRUE",

// reference clock 300MHz and 400MHz generation with MMCM
  generate
    if (REF_CLK_MMCM_IODELAY_CTRL == "TRUE") begin: clk_ref_mmcm_gen
      MMCME2_ADV
      #(.BANDWIDTH            ("HIGH"),
        .CLKOUT4_CASCADE      ("FALSE"),
        .COMPENSATION         ("INTERNAL"),
        .STARTUP_WAIT         ("FALSE"),
        .DIVCLK_DIVIDE        (1),
        .CLKFBOUT_MULT_F      (6),
        .CLKFBOUT_PHASE       (0.000),
        .CLKFBOUT_USE_FINE_PS ("FALSE"),
        .CLKOUT0_DIVIDE_F     (4),
        .CLKOUT0_PHASE        (0.000),
        .CLKOUT0_DUTY_CYCLE   (0.500),
        .CLKOUT0_USE_FINE_PS  ("FALSE"),
        .CLKOUT1_DIVIDE       (3),
        .CLKOUT1_PHASE        (0.000),
        .CLKOUT1_DUTY_CYCLE   (0.500),
        .CLKOUT1_USE_FINE_PS  ("FALSE"),
        .CLKIN1_PERIOD        (5),
        .REF_JITTER1          (0.000))
      mmcm_i
        // Output clocks
       (.CLKFBOUT            (mmcm_clkfbout),
        .CLKFBOUTB           (),
        .CLKOUT0             (clk_ref_mmcm_300),
        .CLKOUT0B            (),
        .CLKOUT1             (clk_ref_mmcm_400),
        .CLKOUT1B            (),
        .CLKOUT2             (),
        .CLKOUT2B            (),
        .CLKOUT3             (),
        .CLKOUT3B            (),
        .CLKOUT4             (),
        .CLKOUT5             (),
        .CLKOUT6             (),
         // Input clock control
        .CLKFBIN             (mmcm_clkfbout),
        .CLKIN1              (clk_ref_ibufg),
        .CLKIN2              (1'b0),
         // Tied to always select the primary input clock
        .CLKINSEL            (1'b1),
        // Ports for dynamic reconfiguration
        .DADDR               (7'h0),
        .DCLK                (1'b0),
        .DEN                 (1'b0),
        .DI                  (16'h0),
        .DO                  (),
        .DRDY                (),
        .DWE                 (1'b0),
        // Ports for dynamic phase shift
        .PSCLK               (1'b0),
        .PSEN                (1'b0),
        .PSINCDEC            (1'b0),
        .PSDONE              (),
        // Other control and status signals
        .LOCKED              (mmcm_Locked),
        .CLKINSTOPPED        (),
        .CLKFBSTOPPED        (),
        .PWRDWN              (1'b0),
        .RST                 (sys_rst_act_hi));
    end
  endgenerate

  generate
    if (REF_CLK_MMCM_IODELAY_CTRL == "TRUE") begin : clk_ref_300_400_en
      if(FPGA_SPEED_GRADE == 1) begin: clk_ref_300
        BUFG u_bufg_clk_ref_300
          (
           .O (clk_ref[1]),
           .I (clk_ref_mmcm_300)
           );
      end else if (FPGA_SPEED_GRADE == 2 || FPGA_SPEED_GRADE == 3) begin: clk_ref_400
        BUFG u_bufg_clk_ref_400
          (
           .O (clk_ref[1]),
           .I (clk_ref_mmcm_400)
           );
      end
    end
  endgenerate

  generate
    if ((REFCLK_TYPE == "DIFFERENTIAL") ||
        (REFCLK_TYPE == "SINGLE_ENDED") ||
        (REFCLK_TYPE == "USE_SYSTEM_CLOCK" && SYSCLK_TYPE != "NO_BUFFER")) begin: clk_ref_200
      BUFG u_bufg_clk_ref
       (
        .O (clk_ref[0]),
        .I (clk_ref_ibufg)
        );
    end else begin: clk_ref_200_no_buffer
      assign clk_ref[0] = clk_ref_i;
    end
  endgenerate
  //*****************************************************************
  // IDELAYCTRL reset
  // This assumes an external clock signal driving the IDELAYCTRL
  // blocks. Otherwise, if a PLL drives IDELAYCTRL, then the PLL
  // lock signal will need to be incorporated in this.
  //*****************************************************************
  // Add PLL lock if PLL drives IDELAYCTRL in user design
  assign rst_tmp_idelay = sys_rst_act_hi;


  generate
    if (REF_CLK_MMCM_IODELAY_CTRL == "TRUE") begin: rst_ref_gen_1
      always @(posedge clk_ref[1] or posedge rst_tmp_idelay)
        if (rst_tmp_idelay)
          rst_ref_sync_r[1] <= #TCQ {RST_SYNC_NUM{1'b1}};
        else
          rst_ref_sync_r[1] <= #TCQ rst_ref_sync_r[1] << 1;
      assign rst_ref[1]  = rst_ref_sync_r[1][RST_SYNC_NUM-1];
    end
  endgenerate

  always @(posedge clk_ref[0] or posedge rst_tmp_idelay)
    if (rst_tmp_idelay)
      rst_ref_sync_r[0] <= #TCQ {RST_SYNC_NUM{1'b1}};
    else
      rst_ref_sync_r[0] <= #TCQ rst_ref_sync_r[0] << 1;

  assign rst_ref[0]  = rst_ref_sync_r[0][RST_SYNC_NUM-1];
  //*****************************************************************
  generate
    if (REF_CLK_MMCM_IODELAY_CTRL == "TRUE") begin: idelayctrl_gen_1
      (* IODELAY_GROUP = IODELAY_GRP1 *) IDELAYCTRL u_idelayctrl_300_400
        (
         .RDY    (iodelay_ctrl_rdy[1]),
         .REFCLK (clk_ref[1]),
         .RST    (rst_ref[1])
         );
    end
  endgenerate
  (* IODELAY_GROUP = IODELAY_GRP0 *) IDELAYCTRL u_idelayctrl_200
    (
     .RDY    (iodelay_ctrl_rdy[0]),
     .REFCLK (clk_ref[0]),
     .RST    (rst_ref[0])
     );

芯片型号为:XC7Z100-FFG900-2,速度等级是2,此处使用的参考时钟为400MHz。
输出的时钟,通过仿真图观察下:
输入clk_ref_i=3333ps+1667ps=5000ps,时钟频率为200M
输出clk_ref_mmcm_300=3333ps,时钟频率为300M
在这里插入图片描述

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
vivado是一种用于设计、验证和实现FPGA(可编程逻辑电路)的软件开发环境。DDR3 MIG是vivado中的DDR3 SDRAM控制器DDR3 MIG的脚约束是指对于DDR3 MIG上的各个引脚进行约束设置,以确保其在系统中正常工作。脚约束可以包括时钟信号、数据信号、控制信号等的引脚位置和电气特性。 在进行DDR3 MIG脚约束时,需要先了解DDR3 MIG的引脚定义和要求。根据DDR3 MIG的手册或数据表,可以获取到各个引脚的名称、类型、电气特性等重要信息。 然后,在vivado的工程中,打开约束文件(.xdc文件),可以使用Xilinx自带的约束语言(XDC)进行脚约束的设置。在约束文件中,根据DDR3 MIG的引脚定义,对每个引脚进行适当的约束定义。 脚约束的设置包括但不限于以下几个方面:设置时钟约束,包括主时钟和辅助时钟的频率、相位等;设置数据引脚的约束,包括信号延迟、时序等;设置控制引脚的约束,如命令信号和读/写使能信号的时序等。 在设置脚约束时,需要根据DDR3 MIG的规格手册和工程需求,合理选择约束参数并进行设置。同时,也可以通过vivado提供的约束设置工具来自动生成一些基本的脚约束。 设置完脚约束后,可以进行综合、实现和验证等步骤,确保DDR3 MIGFPGA中的正常工作。如果出现设计错误或时序冲突等问题,可以根据报错信息和约束文件进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小灰灰的FPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值