FPGA学习笔记:PLL IP核的使用方法

描述

理论学习

IP理论学习

IP(Intellectual Property)是知识产权的意思,半导体行业的IP是“用于ASIC或FPGA中的预先设计好的电路功能模块”。一些常用的复杂的功能模块(如FIFO、RAM、FIR滤波器、SDRAM控制器、PCIE接口等),不可能每次使用都要用户自行设计,所以可以将其设计成 参数可修改的模块 ,其他用户可以直接调用。具有复杂功能和商业价值的IP核一般具有知识产权。

IP核有三种不同的存在形式: HDL语言形式,网表形式、版图形式 。分别对应三类IP内核: 软核、固核和硬核

软核:通常是以硬件描述语言HDL源文件的形式出现,大多数应用于FPGA的IP内核均为软核。软核通常以加密形式提供,RTL对用户不可见,但布局和布线灵活。在这些加密的软核中,如果对内核进行了参数化,那么用户就可通过头文件或图形用户接口(GUI)方便地对参数进行操作。

固核:完成了综合的功能块,以网表的形式交给客户使用。对于那些对时序要求严格的内核(如PCIE接口内核),可预布线特定信号或分配特定的布线资源,以满足时序要求。内核是预先设计的,可能会影响整体设计,例如:由于内核的建立时间、保持时间和握手信号都可能是固定的,因此其它电路的设计时都必须考虑与该内核进行正确地接口。如果内核具有固定布局或部分固定的布局,那么这还将影响其它电路的布局。

硬核:最终阶段产品——掩膜(Mask),以经过完全的布局布线的网表形式提供。硬核缺乏灵活性且可移植性差,但由于无须提供RTL文件,更易于实现IP保护。比如一些FPGA芯片内置的ARM核就是硬核。

IP核也有缺点:1、不同的厂商会有自己的IP且一般不通用,不好移植,如果之前用的一个厂商的某个IP核,改用另一个厂商就需要将整个IP核替换。2、IP核实质是个加密的 黑匣子 ,如果出现问题或者想优化都不好修改。3、有些定制的IP核会很贵。

Altera公司提供两类功能模块:免费的LPM宏功能模块(Megafunction/LPM)和需要授权使用的IP知识产权(MegaCore),两者的实现功能上有区别,使用方法相同。Altera IP核有逻辑运算IP核,数学运算IP核,存储器类IP核,数字信号处理IP核,数字通信IP核,图像处理IP核,输入/输出IP核,芯片接口IP核,设计调试IP核等等。

这里通过Quartus II中MegaWizard插件管理器去例化IP核。(非Altera的第三方IP核以网表文件方式提供)。在MegaWizard插件管理中可以创建、定制和例化Altera IP核。

PLL理论知识

PLL(Phase Locked Loop,即锁相环)是最常用的IP核之一,可以对输入到FPGA的时钟信号进行任意 分频、倍频、相位调整、占空比调整 ,输出期望时钟。即使不改变输入时钟,也会使用PLL,因为经过 PLL 后的时钟在抖动(Jitter)方面的性能更好一些。

PLL的结构如图所示:

fifo

能够看出来这个系统是闭环负反馈系统。

FD/PD是鉴频鉴相器,参考时钟(ref_clk)通过鉴频(FD)鉴相器(PD)和输出的时钟频率进行比较,参考时钟频率等于输出时钟频率则鉴频鉴相器输出为0,如果参考时钟频率比较大则鉴频鉴相器输出>1的值,如果参考时钟频率较小则鉴频鉴相器输出<1的值。

LF是环路滤波器,用于控制噪声的带宽,滤掉高频噪声,将带有噪声的波形变平滑。

VCO是压控振荡器,LF输出的电压越大,VCO输出的频率越高,然后将这个频率信号连接到鉴频鉴相器作为需要比较的频率。

PLL的作用是让期望得到的输出时钟与参考时钟的频率逐渐相等并稳定。

倍频的实现: 在VCO后接一个分频器,分频后的pll_out频率等于ref_clk频率,那么pll_out频率就是ref_clk频率的倍频

fifo

分频的实现: 在参考时钟后接一个分频器,ref_clk分频后频率等于pll_out频率,那么pll_out是ref_clk的分频

fifo

具体步骤

首先依然是创建prj,rtl,sim文件夹,prj中放工程,rtl中放综合用的.v文件,sim中放testbench文件。建立工程,工程名为pll。工程名,顶层的文件名,顶层模块名最好都保持一致,否则可能会报错。另外在prj文件中建立一个子文件夹ipcore用来放工程中可能用到的ip,ipcore文件夹下再放一个pll_ip文件夹,表示存放的是pll的ip。养成良好的习惯,有助于以后在复杂工程里方便的查找文件,也方便别人阅读。然后打开MegaWizard Plug,创建ip并配置ip:

Tools-MegaWizard Plug-In Manager-creat a new custom megafunction variation-next

fifo

fifo

fifo

后面配置扩展频谱时钟和带宽可编程,配置时钟切换,PLL重新配置都用默认项,都是高级设置。到output clock设置页面就要进行输出时钟的参数配置。

fifo

我们将c0设置为输入时钟的2倍频,c1设置为2分频,c2设置为相移90°,c3设置为占空比20%,如下图所示:

fifo

fifo

fifo

fifo

fifo

接下来是EDA配置界面,可以直接点击“Next”。

fifo

这里显示了我们在仿真PLL IP核时所需要的Altera的仿真库,使用NativeLink联合ModelSim的仿真时不需要关心这个仿真库,设置好NativeLink后系统会自动帮我们添加这个仿真库的,但如果使用ModelSim单独进行仿真时不添加该仿真库就会报错,这里提示了我们需要添加哪些库才能够满足ModelSim的单独仿真。

接下来是Summary(总体设置)界面,显示的是配置好PLL IP核后要输出的文件,其中“pll_ip.v”和“pll_ip.ppf”是默认输出的,不可以取消。此外我们再将“pll_ip_inst.v”这个实例化模板文件添加上,方便我们实例化时使用,其余的文件都不要勾选。

fifo

在弹出的页面中勾选,可以把.qip文件添加到file目录下

fifo

也可以手动把.qip文件添加到file目录下

fifo

创建和设置完Ip后可以观察到ipcore文件夹中生成了.ppf文件,.qip文件,pll_ip.v文件,pll_ip_inst.v文件。

.qip文件可以通过手动添加的方式或者弹窗确定的方式添加到工程结构中。

pll_ip.v和pll_ip_inst.v文件是根据我们设置好的ip参数生成的,如果不想改变输出时钟就不要改变里面的内容。pll的ip(atpll)可以看作一个器件,我们不需要也不能了解内部构造,只能通过配置参数进行设计,得到想要的输出。我们通过图形化界面的配置会生成pll_ip.v文件,文件中定义了pll_ip module,输入是我们定义的50MHz的时钟,输出是我们定义的c0,c1,c2,c3和locked。实例化atpll黑匣子模块,将定义的6个输入输出与atpll模块相连,我们的pll_ip模块就具有了自定义的锁相环功能,其他引脚没有被使用,就是默认的配置。还生成了pll_ip_inst.v文件,是将pll_ip模块进行实例化。

接下来需要将pll的ip当作一个子模块,实例化并调用它,写成顶层模块pll

编写代码

module pll
(
input wire sys_clk , 
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_ip pll_ip_inst
 (
 .inclk0 (sys_clk ), 
 .c0 (clk_mul_2 ), 
 .c1 (clk_div_2 ), 
 .c2 (clk_phase_90 ), 
 .c3 (clk_ducle_20 ),
 .locked (locked )
 );


 endmodule

pll模块的输入为系统时钟50MHz,输出信号名称分别对应各自的特性

pll_ip模块中定义的输入和输出引脚,在实例化时,通过信号名称关联进行引用。c0就是2倍频,c1就是2分频...

fifo

Testbench

Testbench文件是tb_pll.v,testbench的原理是将顶层模块作为待测件DUT,定义一个时钟输入作为DUT的激励,并观察输出波形,如果得到了预想的波形说明我们的程序没有问题。模块必须要经过实例化才能调用,这里想调用顶层模块作为被测件,我们需要实例化pll.v并重新连接输入输出。

`timescale 1ns/1ns
module tb_pll();


 reg sys_clk;
 wire clk_mul_2 ;
 wire clk_div_2 ;
 wire clk_phase_90;
 wire clk_ducle_20;
 wire locked ;


 //初始化系统时钟
 initial sys_clk = 1'b1;


 //sys_clk:模拟系统时钟,每10ns电平翻转一次,周期为20ns,频率为50MHz
 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

时钟信号用寄存器reg变量进行定义,剩下的几个输出变量都用wire等同于物理连线。

初始化:时钟初始为高电平

模拟系统时钟:我们需要给DUT一个激励时钟,频率为50MHz,因此每延时10ns要翻转一次电平

实例化pll模块:用物理连线将tb_pll模块的输入输出和pll模块的输入输出连接,那么tb_pll的输出就是DUT对模拟系统时钟的响应。通过modelsim观察输出信号,就可以判断是否达到理想结果。

波形分析

fifo

和预想一致

说在后面:IP核给我们一种很好的学习思路,在使用一个模块时,可以先不必看懂他的代码,只需要根据模块的作用进行实例化就可以完成我们想要的设计!

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分