【小知识】关于时钟的MMCME_ADV原语的探讨

我们这些菜鸟都是使用IP配参生成调用文件,只有高手级别才会使用时钟MMCM原语,就像自己玩linux用GUI,高手玩linux自己搭环境。

xilinx时钟IP使用参考官方文档http://www.xilinx.com/support/documentation/ip_documentation/clk_wiz/v6_0/pg065-clk-wiz.pdficon-default.png?t=M276http://www.xilinx.com/support/documentation/ip_documentation/clk_wiz/v6_0/pg065-clk-wiz.pdf

虽然直接调用IP核好用,但是原语也有原语的优势,就是代码移植中的优势了,当然,如果接手大佬的工程,不知道MMCM是什么电路,啥配啥,那就只能啥啥啥了,这里是通过xilinx官方IP直接看官方配置,来理解MMCM原语配置

1.参数

时钟输入:50MHz;

时钟输出:25MHz、50MHz、100MHz、125MHz、200MHz、200MHz反相;

2.IP核配置

在IP集合中搜索clock,找到相应IP核

 使用MMCM类型,配置输入时钟为单端50MHz

时钟输出设置,分别设置25MHz、50MHz、100MHz、125MHz、200MHz以及200MHz反相

 启用低复位有效端口reset和锁定标志locked

 默认

 MMCM设置,默认

 核配置状态确认

生成IP 

 

 例化文件

//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG

  clk_wiz_0 instance_name
   (
    // Clock out ports
    .clk_out1(clk_out1),     // output clk_out1
    .clk_out2(clk_out2),     // output clk_out2
    .clk_out3(clk_out3),     // output clk_out3
    .clk_out4(clk_out4),     // output clk_out4
    .clk_out5(clk_out5),     // output clk_out5
    .clk_out6(clk_out6),     // output clk_out6
    // Status and control signals
    .resetn(resetn), // input resetn
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(clk_in1));      // input clk_in1
// INST_TAG_END ------ End INSTANTIATION Template ---------

3.IP核源码官方配置

此处可以查看IP核的源码

 对应官方源码如下

//----------------------------------------------------------------------------
// User entered comments
//----------------------------------------------------------------------------
// None
//
//----------------------------------------------------------------------------
//  Output     Output      Phase    Duty Cycle   Pk-to-Pk     Phase
//   Clock     Freq (MHz)  (degrees)    (%)     Jitter (ps)  Error (ps)
//----------------------------------------------------------------------------
// clk_out1____25.000______0.000______50.0______236.428____164.985
// clk_out2____50.000______0.000______50.0______192.113____164.985
// clk_out3___100.000______0.000______50.0______162.035____164.985
// clk_out4___125.000______0.000______50.0______154.207____164.985
// clk_out5___200.000______0.000______50.0______142.107____164.985
// clk_out6___200.000____180.000______50.0______142.107____164.985
//
//----------------------------------------------------------------------------
// Input Clock   Freq (MHz)    Input Jitter (UI)
//----------------------------------------------------------------------------
// __primary__________50.000____________0.010

`timescale 1ps/1ps

module clk_wiz_0_clk_wiz 

 (// Clock in ports
  // Clock out ports
  output        clk_out1,
  output        clk_out2,
  output        clk_out3,
  output        clk_out4,
  output        clk_out5,
  output        clk_out6,
  // Status and control signals
  input         resetn,
  output        locked,
  input         clk_in1
 );
  // Input buffering
  //------------------------------------
wire clk_in1_clk_wiz_0;
wire clk_in2_clk_wiz_0;
  IBUF clkin1_ibufg
   (.O (clk_in1_clk_wiz_0),
    .I (clk_in1));


  // Clocking PRIMITIVE
  //------------------------------------

  // Instantiation of the MMCM PRIMITIVE
  //    * Unused inputs are tied off
  //    * Unused outputs are labeled unused

  wire        clk_out1_clk_wiz_0;
  wire        clk_out2_clk_wiz_0;
  wire        clk_out3_clk_wiz_0;
  wire        clk_out4_clk_wiz_0;
  wire        clk_out5_clk_wiz_0;
  wire        clk_out6_clk_wiz_0;
  wire        clk_out7_clk_wiz_0;

  wire [15:0] do_unused;
  wire        drdy_unused;
  wire        psdone_unused;
  wire        locked_int;
  wire        clkfbout_clk_wiz_0;
  wire        clkfbout_buf_clk_wiz_0;
  wire        clkfboutb_unused;
    wire clkout0b_unused;
   wire clkout1b_unused;
   wire clkout2b_unused;
   wire clkout3b_unused;
  wire        clkout6_unused;
  wire        clkfbstopped_unused;
  wire        clkinstopped_unused;
  wire        reset_high;

  MMCME2_ADV
  #(.BANDWIDTH            ("OPTIMIZED"),
    .CLKOUT4_CASCADE      ("FALSE"),
    .COMPENSATION         ("ZHOLD"),
    .STARTUP_WAIT         ("FALSE"),
    .DIVCLK_DIVIDE        (1),
    .CLKFBOUT_MULT_F      (20.000),
    .CLKFBOUT_PHASE       (0.000),
    .CLKFBOUT_USE_FINE_PS ("FALSE"),
    .CLKOUT0_DIVIDE_F     (40.000),
    .CLKOUT0_PHASE        (0.000),
    .CLKOUT0_DUTY_CYCLE   (0.500),
    .CLKOUT0_USE_FINE_PS  ("FALSE"),
    .CLKOUT1_DIVIDE       (20),
    .CLKOUT1_PHASE        (0.000),
    .CLKOUT1_DUTY_CYCLE   (0.500),
    .CLKOUT1_USE_FINE_PS  ("FALSE"),
    .CLKOUT2_DIVIDE       (10),
    .CLKOUT2_PHASE        (0.000),
    .CLKOUT2_DUTY_CYCLE   (0.500),
    .CLKOUT2_USE_FINE_PS  ("FALSE"),
    .CLKOUT3_DIVIDE       (8),
    .CLKOUT3_PHASE        (0.000),
    .CLKOUT3_DUTY_CYCLE   (0.500),
    .CLKOUT3_USE_FINE_PS  ("FALSE"),
    .CLKOUT4_DIVIDE       (5),
    .CLKOUT4_PHASE        (0.000),
    .CLKOUT4_DUTY_CYCLE   (0.500),
    .CLKOUT4_USE_FINE_PS  ("FALSE"),
    .CLKOUT5_DIVIDE       (5),
    .CLKOUT5_PHASE        (180.000),
    .CLKOUT5_DUTY_CYCLE   (0.500),
    .CLKOUT5_USE_FINE_PS  ("FALSE"),
    .CLKIN1_PERIOD        (20.000))
  mmcm_adv_inst
    // Output clocks
   (
    .CLKFBOUT            (clkfbout_clk_wiz_0),
    .CLKFBOUTB           (clkfboutb_unused),
    .CLKOUT0             (clk_out1_clk_wiz_0),
    .CLKOUT0B            (clkout0b_unused),
    .CLKOUT1             (clk_out2_clk_wiz_0),
    .CLKOUT1B            (clkout1b_unused),
    .CLKOUT2             (clk_out3_clk_wiz_0),
    .CLKOUT2B            (clkout2b_unused),
    .CLKOUT3             (clk_out4_clk_wiz_0),
    .CLKOUT3B            (clkout3b_unused),
    .CLKOUT4             (clk_out5_clk_wiz_0),
    .CLKOUT5             (clk_out6_clk_wiz_0),
    .CLKOUT6             (clkout6_unused),
     // Input clock control
    .CLKFBIN             (clkfbout_buf_clk_wiz_0),
    .CLKIN1              (clk_in1_clk_wiz_0),
    .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                  (do_unused),
    .DRDY                (drdy_unused),
    .DWE                 (1'b0),
    // Ports for dynamic phase shift
    .PSCLK               (1'b0),
    .PSEN                (1'b0),
    .PSINCDEC            (1'b0),
    .PSDONE              (psdone_unused),
    // Other control and status signals
    .LOCKED              (locked_int),
    .CLKINSTOPPED        (clkinstopped_unused),
    .CLKFBSTOPPED        (clkfbstopped_unused),
    .PWRDWN              (1'b0),
    .RST                 (reset_high));
  assign reset_high = ~resetn; 

  assign locked = locked_int;
// Clock Monitor clock assigning
//--------------------------------------
 // Output buffering
  //-----------------------------------

  BUFG clkf_buf
   (.O (clkfbout_buf_clk_wiz_0),
    .I (clkfbout_clk_wiz_0));

  BUFG clkout1_buf
   (.O   (clk_out1),
    .I   (clk_out1_clk_wiz_0));

  BUFG clkout2_buf
   (.O   (clk_out2),
    .I   (clk_out2_clk_wiz_0));

  BUFG clkout3_buf
   (.O   (clk_out3),
    .I   (clk_out3_clk_wiz_0));

  BUFG clkout4_buf
   (.O   (clk_out4),
    .I   (clk_out4_clk_wiz_0));

  BUFG clkout5_buf
   (.O   (clk_out5),
    .I   (clk_out5_clk_wiz_0));

  BUFG clkout6_buf
   (.O   (clk_out6),
    .I   (clk_out6_clk_wiz_0));


endmodule

从以上该IP对应的Xilinx官方源码可以看出IP核使用了原语 MMCME2_ADV 和 BUFG 。

分析原语参数如下:

 ​​​​​​​

 

 重点来了↓↓↓

 从以上数据看,貌似输入时钟50*20等于输出时钟200*5的关系,可惜不是,因为

就是说,任何使用MMCM电路的,其输入时钟都要VCO,然后再统一分配出去 ,所以说,上一个例子只是巧合,因为VCO是1000MHz

 官方: VCO Frequency = (Input Clock Frequency) * (CLKFBOUT_MULT)/DIVCLK_DIVIDE

 那验证一下,用33MHz输入试试

 

所以,clkout_freq = VCO_freq / DIV  ;

MMCM原语与时钟输入输出相关的常用参数配置基本上就是这些了。

<think>好的,用户想了解如何在Vivado中使用MMCME2_ADV原语,并希望有示例说明。首先,我需要回忆一下MMCME2_ADV的基本信息。它是Xilinx FPGA中用于时钟管理的重要模块,属于混合模式时钟管理器,用于频率合成、相位调整和抖动过滤等。用户可能需要生成特定频率的时钟,或者调整相位关系,所以需要知道如何配置参数和例化该原语。 接下来,我应该考虑用户可能的背景。可能是一位FPGA工程师,正在处理时钟设计,遇到了需要手动例化MMCM的情况,而不仅仅依赖Vivado的自动生成。用户可能需要具体的代码示例和参数解释,以确保正确配置。 需要分步骤讲解使用方法。首先,原语的基本功能,然后是参数配置,如输入时钟频率、输出时钟需求、反馈模式等。接着是端口说明,如CLKIN1、CLKOUT0等。然后给出一个示例,说明如何根据需求计算参数,并编写Verilog代码。可能还要提醒用户注意时钟约束和Vivado的时钟向导工具,作为辅助手段。 需要检查是否有常见的错误点,比如反馈模式的选择(内部或外部),分频系数的计算,以及动态重配置的接口使用。此外,确保提到的参数名称和法正确,比如CLKFBOUT_MULT_F、CLKOUT0_DIVIDE_F等,这些是MMCME2_ADV的关键参数。 用户可能还需要知道如何验证配置,比如通过仿真或硬件测试,但问题主要集中在使用方法上,所以可能不需要深入验证部分。但可以提及需要添加时钟约束,如create_clock,以确保时序分析正确。 最后,整理结构,先介绍原语的作用,然后详细参数配置,示例代码,并注意事项。确保用中文,术准确,步骤清晰。避免使用Markdown格式,保持自然的口化表达,但转换为书面说明。</think>在Vivado中使用MMCME2_ADV原语的步骤如下(以生成100MHz输入转200MHz输出为例): 1. **原语功能说明** MMCME2_ADV是Xilinx 7系列FPGA时钟管理模块,支持: - 6路独立输出时钟 - 动态相位调整 - 频率合成(1.6MHz至800MHz输出) - 输入抖动滤波 2. **关键参数配置** ```verilog MMCME2_ADV #( .BANDWIDTH("OPTIMIZED"), // 抖动滤波模式 .CLKIN1_PERIOD(10.0), // 输入时钟周期10ns(100MHz) .CLKFBOUT_MULT_F(10.0), // 反馈乘法系数 .DIVCLK_DIVIDE(1), // 输入分频系数 .CLKOUT0_DIVIDE_F(5.0), // 输出分频系数 .CLKOUT0_PHASE(0.0) // 相位偏移 ) ``` *频率计算公式*: $$ f_{out} = \frac{f_{in} \times CLKFBOUT\_MULT\_F}{DIVCLK\_DIVIDE \times CLKOUT0\_DIVIDE\_F} $$ 本例中:$200MHz = \frac{100MHz \times 10}{1 \times 5}$ 3. **端口连接示例** ```verilog MMCME2_ADV mmcm_inst ( // 基础时钟端口 .CLKIN1(clk_100m), // 输入时钟 .CLKFBIN(clk_fb), // 反馈时钟 .CLKFBOUT(clk_fb), // 反馈输出 .CLKOUT0(clk_200m), // 主输出时钟 // 控制信号 .PWRDWN(1'b0), // 常使能 .RST(reset), // 复位信号 // 动态重配置端口(可选) .DADDR(7'h0), .DI(16'h0), .DWE(1'b0), .DEN(1'b0), .DCLK(1'b0) ); ``` 4. **注意事项** - 必须添加时钟约束: ```tcl create_clock -period 10.000 [get_ports clk_100m] ``` - 反馈模式选择: - *内部反馈*:CLKFBIN连接CLKFBOUT - *外部反馈*:通过FPGA引脚连接 - 推荐使用Clock Wizard生成初始配置,再手动优化参数 5. **典型应用场景** - 生成视频像素时钟(如148.5MHz) - 高速SerDes参考时钟 - 多时钟域系统的时钟生成 建议配合Vivado的时钟网络分析工具(Clock Interaction Report)验证时序裕量。实际开发中可通过DRP(Dynamic Reconfiguration Port)接口实现运行时频率调整。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值