一、PLL IP 核配置
首先创建一个名为 ip_clk_wiz 的工程,
在 IP Catalog 下找到 ALTPLL IP 核, 也可以直接在搜索框中输入 ALTPLL 找到它。
我们找到 ALTPLL IP 核以后, 单击选中它,然后我们需要为 ALTPLL IP 核选择保存的路径及名称,首先大家先在工程所在路径 prj 文件夹下创建一个文件夹 ipcore,用于存放工程中用到的 IP 核(如果之前没有创建 ipcore 文件夹的话),然后在“What name do you want for the output file”一栏中输入 IP 存放的路径及名称, 这里我们命名为 ip_pll 并且选择创建的 IP 核代码为 Verilog HDL。

完成这些设置以后,我们点击【 OK】,

晶振的时钟频率为 50Mhz,因此在上图所示页面修改成 50Mhz。
另外 PLL 支持4 种工作模式:
In normal mode( 正常模式):
PLL 反馈路径源是全局或局域时钟网络,可以最小化时钟类型和指定PLL 寄存器的时钟延时,还可以指定补偿的 PLL 输出。
In source-synchronous compensation mode(源同步模式):
数据和时钟信号同时到达输入引脚。从引脚到 I/O 输入寄存器之间的时钟延时与从引脚到 I/O 输入寄存器之间的数据延时匹配,信号可以确保在任何输入/输出使能寄存器的时钟和数据端口有相同的相位关系。
In zero delay buffer mode( 零延时缓存模式):
PLL 反馈路径限制在专用 PLL 外部输出引脚上。片外驱动的 PLL 反馈路径与时钟输入是相位对齐的,且时钟输入和外部时钟输出之间的延时最小。
Witch no compensation( 外部反馈模式):
PLL 补偿到 PLL 的反馈输入,这样可以最小化输入时钟和反馈时钟引脚之间的延时。
通常保持默认设置, 选择 In normal mode( 正常模式) 即可。
然后我们直接点击【 Next>】,

上图中第一个红框标出的位置是设置是否使用异步复位来复位锁相环,
第二个红框标出的位置是是否输出 LOCK 信号, LOCK 信号拉高表示锁相环开始稳定输出时钟信号, 复位信号是高电平有效。
Advanced Parameters 为高级参数配置,用于高级 PLL 参数输出文件,且不支持使用级联计数器的输出时钟(S)配置。
在此我们保持默认的设置,直接点击【 Next>】,

Bandwidth 为频带宽度,较低的带宽将导致输入抖动抑制和减少切换期间的漂移,而代价是较慢的
PLL 锁定时间。
这里我们选择默认即可,然后继续点击【 Next>】,

Clock Switchover:
为时钟转换配置页面是配置另一个时钟输入源, 由于我们PCB上只有一个 50Mhz的晶振,且一般也不需要使用两个。
所以这里保持默认即可, 直接点击【 Next>】,

Dynamic Reconfiguration:为动态重新配置选项,主要为动态重新配置,用于非相位(如频率,占空比,带宽等)的重新配置。
Initial Configuration File:为初始配置文件。
Additional Configuration File:为附加配置文件,这里均为灰色选项,了解即可。
Dynamic Phase Reconfiguration:为动态相位重构,可以选择启用相移阶跃分辨率, 为动态相位重新配置创建可选输入。
上图中的页面是选择动态配置 PLL 输出,实现在线的实时配置,我们使用的时钟输出一般都是固定频率的, 所以不需要选择,直接点击【 Next>】,

接下来就进入到配置输出时钟的页面了,
Requested Setting 一栏中直接输入我们需要的时钟频率100Mhz;
Clock phase shift 一栏中输入时钟的相位偏移,这里保持默认为 0 即可;
Clock duty cycle( %) 一栏设置时钟的占空比,时钟占空比一般为 50%, 我们在这里保持默认 50 即可。
Enter output clock parameter 选项,它的作用主要是用来调节倍频系数以及时钟分频系数,目前了解即可。
然后点击【 Next>】,

在该页面中,我们使能 c1 时钟信号,然后将 c1 时钟设置为 100MHz,将时钟相位设置成 180,然后点击【 Next>】,

在该页面中,我们使能 c2 时钟信号,然后将 c2 时钟设置为 50MHz,然后点击【 Next>】,

在该页面中,我们使能 c3 时钟信号,然后将 c3 时钟设置为 25MHz。然后点击【 Next>】,

本次实验只需要用到这四个时钟,因此直接点击【 Next>】,

从该页面中,我们可以看出,如果我们想要仿真 PLL IP 核,那么我们需要添加 altera_mf 仿真库。
如果我们想要将此 PLL IP 核用在其他的 EDA 工具上,我们可以通过选择 Generate netlist 这个选项来生成IP_syn.v 文件,用于其他的 EDA 工具中。
这里需要注意的是,并不是所有的第三方 EDA 工具都支持。
在这里直接点击【 Next】,

然后我们点击【 Finish】完成整个 IP 核的创建。
接下来 Quartus II 软件会在 ipcore 文件夹下创建ALTPLL 的 IP 核文件,然后询问我们是否添加至工程,点击“ YES”按钮将生成的 IP 核添加至工程,

接下来返回到工程界面,在 File 界面里,我们可以看到生成的 ip_pll.qip 和 ip_pll.v 已经添加到工程中。
qip 是 Quartus IP 的缩写, 我们打开 qip 的文件可以看到如图 24.4.16 所示的脚本代码。
上图中红色框标注的意思是 pll_clk.v 文件已经添加至工程里了,
如果在工程中只找到了pll_clk.qip 文件,而没有找到 pll_clk.v 的话也没有关系,工程中只加入 pll_clk.qip 文件也是可以的。
PLL IP 核添加至工程中的页面如图,

二、模块设计
本次实验的目的是通过 PLL IP 核输出四路不同频率或相位的时钟,因此给模块命名为 ip_clk_wiz。
首先想要输出四路不同频率或相位的时钟,就需要输入一个基准时钟,因此实验需要用到系统时钟;
其次为了使程序能恢复至默认状态,系统复位在 FPGA 系统中也是必不可少的;
由此可以分析出,本次实验需要系统时钟和系统复位这两个输入端口,以及四个时钟输出端口,经分析画出模块框图如下所示:

信号名 | 位宽 | 方向 | 端口说明 |
sys_clk | 1 | 输入 | 系统时钟, 50MHz |
sys_rst_n | 1 | 输入 | 系统复位按键,低电平有效 |
clk_100m | 1 | 输出 | 100MHz时钟输出 |
clk_100m_180deg | 1 | 输出 | 100MHz相位偏移180°的时钟输出 |
clk_50m | 1 | 输出 | 50MHz时钟输出 |
clk_25m | 1 | 输出 | 25MHz时钟输出 |
三、绘制波形图
系统时钟为 50MHz,即一个时钟周期为 20ns。
100MHz 的时钟一个时钟周期为 10ns;
100MHz 相位偏移 180°的时钟就相当于将 100MHz 的时钟的高低电平变化做了一个反相处理;
50MHz 的时钟和系统时钟相同;
25MHz 的时钟一个时钟周期为 40ns。
需要注意的是, PLL IP 核会输出一个时钟锁定信号( locked),所有通过 PLL IP 核产生的时钟都是在 locked 为高电平(即时钟已锁定)时才会输出稳定的时钟信号。

这里需要说明一点, 在时钟锁定信号( locked)拉高之前,时钟信号是不稳定,既可能是高电平,也可能是低电平,还可能是不稳定的时钟信号(用示波器或频谱仪可以看到是飘忽不定的),这里绘制时就以低电平来涵盖了。
四、编写代码
首先打开 IP 核的例化模板,在“ File” 窗口中的选项卡中,我们可以看到“ ip_clk_wiz.v” 文件,它是由 IP 核自动生成的只读的 verilog 例化模板文件,双击就可以打开它,在例化时钟 IP 核模块的时候,可以直接从这里拷贝,如下图所示:

接下来我们创建一个 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
//*****************************************************
//PLL IP 核的例化
ip_pll ip_pll_inst (
.areset (~sys_rst_n ),
.inclk0 (sys_clk ),
.c0 (clk_100m ),
.c1 (clk_100m_180deg),
.c2 (clk_50m ),
.c3 (clk_25m ),
.locked (locked )
);
endmodule
程序中例化了 ip_pll_inst,把 FPGA 的系统时钟 50Mhz 连接到 ip_pll_inst 的 inclk0,系统复位信号连接到 ip_pll_inst 的 areset,由于配置时钟 IP 核的复位信号为高电平有效,而输入的系统复位信号 sys_rst_n 是低电平复位,因此要对系统复位信号进行取反。 ip_pll_inst 输出的 4 个时钟信号直接连接到顶层端口的四个时钟输出信号。
五、Modelsim 联合仿真
对 IP 核的仿真需要在 Modeslim 工程中添加 altera_mf 文件仿真库, 仿真库的路径在 Quartus II 软件的安装路径下, 路径为: D:\altera\18.0\quartus\eda\sim_lib\altera_mf.v(如果 Quartus 安装在其它磁盘, 可在对应的安装路径下找到仿真库文件)。
建议把 alerta_mf 文件拷贝到工程的 sim\tb 文件夹下,方便添加至工程。
工程创建完成后,把 tb_ip_pll.v 文件、 ip_pll.v 文件、 pll_clk.v 文件和 altera_mf 文件添加至工程, 然后编译各个文件( 注意 altera_mf 文件编译时间较长), 编译后的工程界面如图 :

六、在 Quartus II 中关联 Modelsim
首先我们打开之前的 Quartus II 工程,在菜单栏中找到【 Tool】→【 Options】按钮,

单击此按钮,在打开的页面左侧我们找到“ EDA Tool Options”点击,

在该页面中, ModelSim 这一栏,我们需要设置 ModelSim 的安装路径下的可执行文件的路径,路径设置完成以后,我们点击【 OK】返回我们的 Quartus II 软件界面。
我们在 Quartus II 软件页面的菜单栏中,我们找到【 Assignments】→【 Settings】按钮,如下图所示页面

单击此按钮,在打开的页面左侧我们找到“ EDA Tool Settings”点击,如下图所示页面。

我们之前创建工程的时候,由于在 Quartus II 软件中没有用到仿真,所以我们将这里设置成了“ None”,现在我们需要用到仿真工具了,我们需要在这里将“ Simulation”设置成“ ModelSim、 Verilog HDL”。
设置完成之后,我们点击【 OK】返回 Quartus II 软件页面中。
6.1 编写TestBench
接下来就是编写仿真文件了。
介绍一下如何使用 Quartus II 软件生成 TestBench 模板,方便编写仿真文件。
在 Quartus II 软件页面的菜单栏中,我们找到【 Processing】→【 Start】→【 Start TestBench Template Writer】按钮,如下图所示:

并点击该按钮,这时 Message 窗口中会显示,如下图所示:

从画横线处我们可以看到 Quartus II 软件已自动给我们生成了一个 TestBench 模板并显示该模块的存放路径,我们只需要找到这个模板并稍作修改就能直接使用了。
我们在工程目录下找到“ ip_clk_wiz.vt”文件,用记事本或 Quartus II 软件打开它进行修改,这里我们在 Quartus II 软件中进行,打开后如下图:

在该图中我们可以看到, Quartus II 软件已经为我们完成了一些基本工作,包括端口部分的代码、变量的声明以及例化测试的工程等,我们要做的就是在这个模板里添加我们需要的测试代码(也就是我们常说的激励)。
eachvec 和@eachvec 是多余的信号,没有特殊的作用,我们可以将它删除也可以不删。修改后的代码如下:
`timescale 1ns / 1ps //仿真单位/仿真精度
module tb_ip_clk_wiz();
//parameter define
parameter CLK_PERIOD = 20; //时钟周期 20ns
//reg define
reg sys_clk;
reg sys_rst_n;
//wire define
wire clk_100m;
wire clk_100m_180deg;
wire clk_50m;
wire clk_25m;
//信号初始化
initial begin
sys_clk = 1'b0;
sys_rst_n = 1'b0;
#200
sys_rst_n = 1'b1;
end
//产生时钟
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
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
修改后将其另存为 tb_ip_clk_wiz.vt,以保持文件名与模块名一致。
6.2 配置仿真环境
接下来我们需要在 Quartus II 软件中配置仿真环境,我们在 Quartus II 软件界面的菜单栏找到【 Assigement】→【 Settings】按钮并打开,在打开的页面中,我们找到左侧的 Simulation 点击,出现如下图所示的页面。

我们选中“Compile Test bench”,然后单击后面的【 Test Benches】按钮,则出现如下图所示的“ Test Benches”窗口:

接着我们单击【 New】按钮,则会出现如下图所示的“ New Test Bench Settings”窗口:

在该页面,将 TestBench 文件名输入到“Test bench name”,将 TestBench 顶层模块名输入到“Top level module in test bench”的编辑栏中,因为一般而言 TestBench 文件名和顶层模块名相同,所以这里只用在“ Test bench name”这一栏输入即可,软件自动同步添加“ Top level module in test bench”。
接着在“ Test bench and simulation files”列表框中添加 TestBench 仿真文件,这里选择 Quartus II 生成的TestBench 模板文件“tb_ip_clk_wiz.vt”。当然了,也可以选择在手动仿真节里编写的“ tb_ip_clk_wiz.v”文件。添加仿真文件如下图:

然后单击【 Add】按钮添加到最下面的列表中。完成后我们单击【 OK】按钮,便可看到下图所示的“ Test benches”窗口的列表中出现了刚才添加的仿真文件相关信息。

然后单击【 OK】按钮,至此,我们仿真文件添加完成了,接着我们单击【 OK】按钮,返回到 Quartus II 软件界面。
6.3 运行RTL仿真(功能仿真)
在 Quartus II 软件界面中的菜单栏中找到【 Tools】→【 Run Simulation Tool】→【 RTL Simulation】按钮,如下图所示界面。

单击此按钮,则会出现如下图所示的波形图界面。
