锁相环作为一种反馈控制电路,其特点是利用外部输入的参考信号控制环路内部震荡信号的频率和相位。因为锁相环可以实现输出信号频率对输入信号频率的自动跟踪,所以锁相环通常用于闭环跟踪电路。锁相环在工作的过程中,当输出信号的频率与输入信号的频率相等时,输出电压与输入电压保持固定的相位差值,即输出电压与输入电压的相位被锁住,这就是锁相环名称的由来。Xilinx 7 系列器件中具有时钟管理单元 CMT 时钟资源,xc7z020 芯片内部有 4 个 CMT,xc7z010 芯片内部有 2 个 CMT,为设备提供强大的系统时钟管理以及高速 I/O 通信的能力。时钟管理单元 CMT 的总体框图如下图所示。
MMCM/PLL 的参考时钟输入可以是 IBUFG(CC)即具有时钟能力的 IO 输入、区域时钟 BUFR、全局时 钟 BUFG、GT 收发器输出时钟、行时钟 BUFH 以及本地布线(不推荐使用本地布线来驱动时钟资源)。在 最多的情况下,MMCM/PLL 的参考时钟输入都是来自 IBUFG(CC)即具有时钟能力的 IO 输入,本实验也是 如此。MMCM/PLL 的输出可以驱动全局时钟 BUFG 和行时钟 BUFH 等等。BUFG 能够驱动整个器件内部的 PL 侧通用逻辑的所有时序单元的时钟端口。BUFG/BUFH/CMT 在一个时钟区域内的连接框图如下图所示。
在本实验中,读者可以简单地理解为:外部时钟连接到具有时钟能力的输入引脚 CCIO(Clock-CapableInput),进入 MMCM/PLL,产生不同频率和不同相位的时钟信号,然后驱动全局时钟资源 BUFG。但是要进行更深入的 FPGA 开发,就必须理解器件的时钟资源架构。有关 Xilinx 时钟资源和 CMT 的更详细信息,读者后期可以花一些时间和精力去学习一下 Xilinx 官方的手册文档“UG472,7 Series FPGAs Clocking Resources User Guide”里的介绍。
MMCM 和 PLL 的总体框图如下图所示。
其中 MMCM 的功能是 PLL 的超集,其具有比 PLL 更强大的相移功能。MMCM 主要用于驱动器件逻辑(CLB、DSP、RAM 等)的时钟。PLL 主要用于为内存接口生成所需的时钟信号,但也具有与器件逻辑的连接,因此如果需要额外的功能,它们可以用作额外的时钟资源。
PLL 由以下几部分组成:前置分频计数器(D 计数器)、相位-频率检测器(PFD,Phase-Frequency Detector)电路,电荷泵(Charge Pump)、环路滤波器(Loop Filter)、压控振荡器(VCO,Voltage Controlled Oscillator)、反馈乘法器计数器(M 计数器)和后置分频计数器(O1-O6 计数器)。
在工作时,PFD 检测其参考频率(FREF)和反馈信号(Feedback)之间的相位差和频率差,控制电荷泵和环路滤波器将相位差转换为控制电压;VCO 根据不同的控制电压产生不同的震荡频率,从而影响 Feedback信号的相位和频率。在 FREF 和 Feedback 信号具有相同的相位和频率之后,就认为 PLL 处于锁相的状态。
在反馈路径中插入M计数器会使VCO的震荡频率是FREF信号频率的M倍,FREF信号等于输入时钟(FIN)除以预缩放计数器(D)。参考频率用以下方程描述:FREF= FIN/D,VCO 输出频率为 FVCO= FIN*M/D,PLL的输出频率为 FOUT=(FIN*M)/(N*O)。
Xilinx 提供了用于实现时钟功能的 IP 核 Clocking Wizard,该 IP 核能够根据用户的时钟需求自动配置器件内部的 CMT 及时钟资源,以实现用户的时钟需求。在这里我们主要讲解的是如何使用该 IP 核,有关该IP 核的更详细介绍,读者可以参阅 Xilinx 官方的手册文档“PG065,Clocking Wizard v6.0 LogiCORE IP Product Guide”。
本节实验任务是使用 Zynq 开发板输出 4 个不同时钟频率或相位的时钟,并在 Vivado 中进行仿真以验证结果,最后生成比特流文件并将下载到开发板上,使用示波器来测量时钟的频率。
本实验中,各端口信号的管脚分配如下表所示:
对应的 XDC 约束语句如下所示:
- set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
- set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
- set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports clk_100m]
- set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports clk_100m_180deg]
- set_property -dict {PACKAGE_PIN P19 IOSTANDARD LVCMOS33} [get_ports clk_50m]
- set_property -dict {PACKAGE_PIN N18 IOSTANDARD LVCMOS33} [get_ports clk_25m]
我们双击“FPGA Features and Design”→“Clocking”下的“Clocking Wizard”,弹出“Customize IP” 窗口,如下图所示。
接下来就是配置 IP 核的时钟参数。最上面的“Component Name”一栏设置该 IP 元件的名称,这里保 持默认即可。在第一个“Clocking Options”选项卡中,“Primitive”选项用于选择是使用 MMCM 还是 PLL 来输 出不同的时钟,对于我们的本次实验来说,MMCM 和 PLL 都可以完成,这里我们可以保持默认选择 MMCM。 需要修改的是最下面的“Input Clock Information”一栏,把“Primary”时钟的输入频率修改为我们开发板的核心板上的晶振频率 50MHz,其他的设置保持默认即可,如下图所示。
接下来切换至“Output Clocks”选项卡,在“Output Clock”选项卡中,勾选前 4 个时钟,并且将其“Output Freq(MHz)”分别设置为 100、100、50、25,注意,第 2 个 100MHz 时钟的相移“Phase(degrees)”一栏要设置为 180。其他设置保持默认即可,如下图所示。、
“Port Renaming”选项卡主要是对一些控制信号的重命名。这里我们只用到了锁定指示 locked 信号,其名称保持默认即可,如下图所示。
“MMCM Setting”选项卡展示了对整个 MMCM/PLL 的最终配置参数,这些参数都是根据之前用户输入的时钟需求由 Vivado 来自动配置,Vivado 已经对参数进行了最优的配置,在绝大多数情况下都不需要用户对它们进行更改,也不建议更改,所以这一步保持默认即可,如下图所示。
最后的“Summary”选项卡是对前面所有配置的一个总结,在这里我们直接点击“OK”按钮即可,如下图所示。
接着就弹出了“Genarate Output Products”窗口,我们直接点击“Generate”即可,如下图所示。
我们接下来创建一个 verilog 源文件,其名称为 ip_clk_wiz.v,代码如下:
- module ip_clk_wiz(
- input sys_clk , //系统时钟
- input sys_rst_n , //系统复位,低电平有效
- //输出时钟
- output clk_100m , //100Mhz时钟频率
- output clk_100m_180deg, //100Mhz时钟频率,相位偏移180度
- output clk_50m , //50Mhz时钟频率
- output clk_25m //25Mhz时钟频率
- );
-
- //wire define
- wire locked;
-
- //*****************************************************
- //** main code
- //*****************************************************
-
- //MMCM/PLL IP核的例化
- clk_wiz_0 clk_wiz_0
- (
- // Clock out ports
- .clk_out1_100m (clk_100m), // output clk_out1_100m
- .clk_out2_100m_180 (clk_100m_180deg), // output clk_out2_100m_180
- .clk_out3_50m (clk_50m), // output clk_out3_50m
- .clk_out4_25m (clk_25m), // output clk_out4_25m
- // Status and control signals
- .reset (~sys_rst_n), // input reset
- .locked (locked), // output locked
- // Clock in ports
- .clk_in1 (sys_clk) // input clk_in1
- );
-
- endmodule
程序中例化了 clk_wiz_0,把 FPGA 的系统时钟 50Mhz 连接到 clk_wiz_0 的 clk_in1,系统复位信号连接到 clk_wiz_0 的 reset,由于时钟 IP 核默认是高电平复位,而输入的系统复位信号 sys_rst_n 是低电平复位,因此要对系统复位信号进行取反。clk_wiz_0 输出的 4 个时钟信号直接连接到顶层端口的四个时钟输出信号。
- `timescale 1ns / 1ps
- module tb_ip_clk_wiz();
-
- reg sys_clk;
- reg sys_rst_n;
-
- wire clk_100m;
- wire clk_100m_180deg;
- wire clk_50m;
- wire clk_25m;
-
- always #10 sys_clk = ~sys_clk;
-
- initial begin
- sys_clk = 1'b0;
- sys_rst_n = 1'b0;
- #200
- sys_rst_n = 1'b1;
- end
- ip_clk_wiz u_ip_clk_wiz(
- .sys_clk (sys_clk ),
- .sys_rst_n (sys_rst_n ),
- .clk_100m (clk_100m ),
- .clk_100m_180deg (clk_100m_180deg),
- .clk_50m (clk_50m ),
- .clk_25m (clk_25m )
- );
-
- endmodule
对模块进行仿真的方法这里不再赘述,仿真后得到的波形如下图所示:
由上图可知,locked 信号拉高之后,锁相环开始输出 4 个稳定的时钟。clk_100m 和 clk_100m_180deg 周期都为 10ns,即时钟频率都为 100Mhz,但两个时钟相位偏移 180 度,所以这两个时钟刚好反相;clk_50m 周期为 20ns,时钟频率为 50Mhz;clk_25m 周期为 40ns,时钟频率为 25Mhz。也就是说,我们创建的锁相环从仿真结果上来看是正确的。
此时在示波器上就可以观察到时钟的波形图。下图为使用示波器测量扩展口第 35 号脚(N18)所显示的波形。
由上图可知,示波器测量出的时钟频率为 25Mhz,跟仿真结果是一样的,其它三个扩展口输出的时钟大家可以测试一下,这里不再贴出其它扩展口的波形图。、
ip_clk_wiz