一、简介
PLL主要由鉴相器(PD)、环路滤波器(LF)和压控振荡器(VCO)三部分组成。鉴相器检测输入信号与VCO输出信号的相位差,并输出一个与相位差成正比的电压信号。该信号经过环路滤波器滤除高频噪声后,作为控制电压输入到VCO,调整其振荡频率,使输出信号的相位逐渐接近输入信号的相位,直至两者相位锁定。
PLL是FPGA重要的资源,不同FPGA的PLL 是不一样。以我们开发板的Cyclone IV为例,它有两个PLL,每个PLL可以提供5路输出。
PLL 的时钟输入可以是PLL 所在的 Bank 的时钟输入管脚或者其他 PLL 的输出,FPGA 内部产生的信号不能驱动PLL。Cyclone IV PLL 产生的时钟可以为单端时钟信号或差分时钟信号, 可以通过GCLK 网络直接驱动 FPGA 外部的 IO 口。
二、PLL的调用
1、首先打开Quartus ,进行工程的创建,这里在前面已经说过怎样创建工程。如果有不会的小伙伴可以在我主页找找。
2、创建好工程之后在右边的IP Catalog 中输入“PLL”搜索IP核。双击选择“ALTPLL”选项。
3、选择好ALT PLL进入到之后,选择我们pll存放的路径(这里我们可以工程文件夹里新建一个ip或者ip_core文件夹,用于存放我们引用的ip核相关的文件)。
文件夹样式:
这里是我保存的文件夹和pll的名字,大家可以参考(这里的名字可以自己取,只要知道就行) ,选择好之后点击“OK”进入下一个界面。
4、 IP核配置界面
如下图,是配置PLL的初始界面,
1是速度等级,由芯片型号决定,不用更改。
2是输入时钟频率,此处修改为50MHz,与开发板匹配。
3是PLL的类型,默认不用修改。
4是PLL的四种输出模式,选择普通模式(In normal mode)即可。
5是补偿输出时钟,不用改。
我们真正需要改的部分就只有2的时钟频率,其他的基本上都是默认选择好的。
5、 这里的optional inputs 我们选择第二个使用异步复位进行pll的复位,在Lock Output我们选择第一个选项创建一个锁定信号locked,当输出时钟达到想要的时钟频率时,locked才为高,系统才会工作。选择好之后点击next。
6、本页面主要是扩展频谱时钟和带宽等参数,保持默认,点击next。
7、这里是第二个时钟信号创建界面,用户可以根据自身看是否需要,这里一般不用选择。
8、这里也保持默认,不用选择。
9、下面是pll输出的时钟设置界面,一个pll总共可以输出5个时钟,可以进行倍频、分频、相位偏移、占空比等的操作 。
1是5个时钟,点击对应的时钟可以进行不同的设置。
2是使用该时钟,要使用这个时钟,这个必须选上,否则使用不了该时钟。
3和4的功能有点相似,都可以对输出时钟频率进行设置,如果使用3的话,√上选项,直接在后面的框中输入想要的频率就可以设置,而选择使用4的话就需要选择相应的分频或者倍频因子,才能得到我们想要的输出频率。4的第一行是倍频因子,第二行是分频因子。
5是时钟占空比,默认为50,根据自己需要进行设置就行。
后面的几个时钟都是按照同样的方式进行修改就行。
10、 时钟设置之后就进入EDA设置界面,这里保持默认。
11、接着就是Summary界面,这里除了默认的ip_pll_bb.v之外,我们还要把ip_pll_inst.v实例化文件勾上,这样在后面的工程里面进行调用或者方针时直接使用就行。
12、最后就是在弹出的界面选择“YES”之后,我们就成功调用了pll。
三、波形仿真
1、调用之后的pll文件,这里名字就是前面我们前面选择存发文件时起的名字。
2、设计文件的编写
在rtl文件中新建一个ip_pll.v文件,对于pll_test.v进行一个调用。其中后面的实例化的代码就是我们直接从pll_test_inst里面复制过来的。
module pll
(
input wire sys_clk , //系统时钟50Mhz
output wire clk_mul_2 , //系统时钟经过2倍频后的时钟
output wire clk_div_2 , //系统时钟经过2分频后的时钟
output wire clk_phase_90, //系统时钟经过相移90°后的时钟
output wire clk_ducle_20, //系统时钟变为占空比为20%的时钟
output wire locked //检测锁相环是否已经锁定,
//只有该信号为高时输出的时钟才是稳定的
);
//------------------------ pll_inst ------------------------
pll_ip pll_ip_inst
(
.inclk0 (sys_clk ), //input inclk0
.c0 (clk_mul_2 ), //output c0
.c1 (clk_div_2 ), //output c1
.c2 (clk_phase_90 ), //output c2
.c3 (clk_ducle_20 ), //output c3
.locked (locked ) //output locked
);
endmodule
3、测试文件的编写
`timescale 1ns/1ns
module tb_pll();
//内部信号定义
wire clk_mul_2 ;
wire clk_div_2 ;
wire clk_phase_90;
wire clk_ducle_20;
wire locked ;
reg sys_clk ;
//初始化系统时钟
initial sys_clk = 1'b1;
always #10 sys_clk = ~sys_clk;
pll pll_inst
(
.sys_clk (sys_clk ), //input sys_clk
.clk_mul_2 (clk_mul_2 ), //output clk_mul_2
.clk_div_2 (clk_div_2 ), //output clk_div_2
.clk_phase_90 (clk_phase_90 ), //output clk_phase_90
.clk_ducle_20 (clk_ducle_20 ), //output clk_ducle_20
.locked (locked ) //output locked
);
endmodule
4、仿真波形图
通过各个时钟输出信号我们可以看到,不同频率的波形对应一致,到这里pll成功调用。