上文 XILINX FPGA IP之MMCM PLL Dynamic Reconfiguration 时钟动态重配详解(1) 对动态重配中用到的寄存器及地址进行了说明,本文对其应用进行说明,同时结合官方例子进行仿真。
针对drp的应用xilinx官网给出了参考设计如下,参考设计有有一个mmcm_drp的模块用来重新配置锁相环的输出。
参考设计的源码下载地址为:https://secure.xilinx.com/webreg/clickthrough.do?cid=179222,大家根据需要进行下载。下面对参考设计进行简要说明。
下载参考设计解压后文件内容如下,MMCME2_DRP、MMCME3_DRP、MMCME4_DRP分别对应7系列、Ultrscl系列、UltrsclPls系列FPGA的MMCM的参考设计代码;PLLE2_DRP、PLLE3_DRP、PLLE4_DRP分别对应7系列、Ultrscl系列、UltrsclPls系列FPGA的PLL的参考设计代码;QuestaSim_Mmcm_Pll_simulation文件夹是仿真文件夹,包括仿真tcl。
拿到参考设计可以直接开始仿真,打开QuestaSim软件,将路径选择到\xapp888\QuestaSim_Mmcm_Pll_simulation\Simulation下,运行do ../SimScripts/MmcmPll_TopFuncSim.tcl,根据提示运行即可打开仿真工程。
运行.tcl首先会提醒,让你检查glbl.v是否存在,然后让修改SimScripts/MmcmPll_FuncSim.do文件中的路径,大家根据自己的安装位置修改相应路径即可。修改完成后输入 x 进入下一步。
然后会提示让输入仿真的器件型号,这里输入7Srs,代表仿真7系列的FPGA芯片,然后让输入仿真用MMCM还是PLL,我选择了MMCM。选择完成后就会运行相应的do文件,开始仿真。
波形文件会自动被do文件创建,直接运行仿真即可。
仿真运行到这里就完了。下面我们去看一下官方参考工程的代码是怎么样的,打开xapp888\MMCME2_DRP\文件夹,如下。
其中,top_mmcme2_tb.v是一个简单的tb,控制切换时钟输出,相当于下边图中的User Logic;top_mmcme2.v包含下面的MMCM_DRP和MMCME2_ADV(MMCM源语);MMCM_DRP.v就是参考例程的分频控制代码。
mmcme2_drp.v代码首先是通过参数例化了两组时钟的输出状态S1 S2,截取部分代码如下
parameter S1_CLKOUT0_DIVIDE = 1, parameter S1_CLKOUT0_PHASE = 0, parameter S1_CLKOUT0_DUTY = 50000, parameter S1_CLKOUT0_FRAC = 125, parameter S1_CLKOUT0_FRAC_EN = 1, // parameter S1_CLKOUT1_DIVIDE = 1, parameter S1_CLKOUT1_PHASE = 0, parameter S1_CLKOUT1_DUTY = 50000, // parameter S1_CLKOUT2_DIVIDE = 1, parameter S1_CLKOUT2_PHASE = 0, parameter S1_CLKOUT2_DUTY = 50000, // parameter S1_CLKOUT3_DIVIDE = 1, parameter S1_CLKOUT3_PHASE = 0, parameter S1_CLKOUT3_DUTY = 50000, // parameter S1_CLKOUT4_DIVIDE = 1, parameter S1_CLKOUT4_PHASE = 0, parameter S1_CLKOUT4_DUTY = 50000, // parameter S1_CLKOUT5_DIVIDE = 1, parameter S1_CLKOUT5_PHASE = 0, parameter S1_CLKOUT5_DUTY = 50000, // parameter S1_CLKOUT6_DIVIDE = 1, parameter S1_CLKOUT6_PHASE = 0, parameter S1_CLKOUT6_DUTY = 50000, parameter S2_CLKOUT0_DIVIDE = 1, parameter S2_CLKOUT0_PHASE = 0, parameter S2_CLKOUT0_DUTY = 50000, parameter S2_CLKOUT0_FRAC = 125, parameter S2_CLKOUT0_FRAC_EN = 1, // parameter S2_CLKOUT1_DIVIDE = 2, parameter S2_CLKOUT1_PHASE = 0, parameter S2_CLKOUT1_DUTY = 50000, // parameter S2_CLKOUT2_DIVIDE = 3, parameter S2_CLKOUT2_PHASE = 0, parameter S2_CLKOUT2_DUTY = 50000, // parameter S2_CLKOUT3_DIVIDE = 4, parameter S2_CLKOUT3_PHASE = 0, parameter S2_CLKOUT3_DUTY = 50000, // parameter S2_CLKOUT4_DIVIDE = 5, parameter S2_CLKOUT4_PHASE = 0, parameter S2_CLKOUT4_DUTY = 50000, // parameter S2_CLKOUT5_DIVIDE = 5, parameter S2_CLKOUT5_PHASE = 0, parameter S2_CLKOUT5_DUTY = 50000, // parameter S2_CLKOUT6_DIVIDE = 5, parameter S2_CLKOUT6_PHASE = -90, parameter S2_CLKOUT6_DUTY = 50000
然后根据管脚输入状态,计算上文中每个寄存器要配置的值,对每个寄存器进行配置,所有的计算函数都在mmcme2_drp_func.h代码中,大家自行查阅。具体的配置过程为:
1、复位MMCM;
2、 daddr 置位、 den拉高,然后等待MMCM送出的DRDY信号;3、送入DI = ((DO and MASK)| BITSET),然后将 den和dwe同时拉高;4、等待MMCM送出的DRDY信号;5、循环上述操作,写入所有寄存器;6、释放MMCM复位,等待MMCM锁定。
仿真中的读写过程如下:
![](https://static.mianbaoban-assets.eet-china.com/xinyu-images/MBXY-CR-a7e04be41112833bd536906ec8d2a70d.png)