我们这些菜鸟都是使用IP配参生成调用文件,只有高手级别才会使用时钟MMCM原语,就像自己玩linux用GUI,高手玩linux自己搭环境。
虽然直接调用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原语与时钟输入输出相关的常用参数配置基本上就是这些了。