本帖最后由 正点原子运营 于 2023-11-15 17:01 编辑
第十七章 IP核之PLL实验
1)实验平台:正点原子 ATK-DFPGL22G开发板
2) 章节摘自【正点原子】ATK-DFPGL22G之FPGA开发指南_V1.0
6)FPGA技术交流QQ群:435699340
PLL的英文全称是Phase Locked Loop,即锁相环,是一种反馈控制电路。PLL对时钟网络进行系统级的时钟管理和偏移控制,具有时钟倍频、分频、相位偏移和可编程占空比的功能。Logos PGL22G芯片内部有6个PLL,为设备提供强大的系统时钟管理以及高速I/O通信的能力。对于一个简单的设计来说,FPGA整个系统使用一个时钟或者通过编写代码的方式对时钟进行分频是可以完成的,但是对于稍微复杂一点的系统来说,系统中往往需要使用多个时钟和时钟相位的偏移,且通过编写代码输出的时钟无法实现时钟的倍频,因此学习PLL IP核的使用方法是我们学习FPGA的一个重要内容。本章我们将通过一个简单的例程来向大家介绍一下PLL IP核的使用方法。 本章包括以下几个部分: 1.1PLL IP核简介 1.2实验任务 1.3硬件设计 1.4程序设计 1.5下载验证
1.1 PLL IP核简介锁相环作为一种反馈控制电路,其特点是利用外部输入的参考信号控制环路内部震荡信号的频率和相位。因为锁相环可以实现输出信号频率对输入信号频率的自动跟踪,所以锁相环通常用于闭环跟踪电路。锁相环在工作的过程中,当输出信号的频率与输入信号的频率相等时,输出电压与输入电压保持固定的相位差值,即输出电压与输入电压的相位被锁住,这就是锁相环名称的由来。
LogosPLL主要由鉴频鉴相器(PFD,Phase Frequency Detector)、环路滤波器(LF,Loop Filter)和压控振荡器(VCO,Voltage Controlled Oscillator)等组成。通过不同的参数配置,可实现信号的调频、调相、同步、频率综合等功能。
LogosPLL的电路框图如下图所示: Logos系列产品的PLL主要特性如下:
1.频率综合,相位调整;
2.可选的输入时钟动态选择;
3.支持外部反馈和内部反馈两种反馈模式;
4.支持PLL的动态配置;
5.可选的输出时钟gate功能;
6.可选的可编程的phase shift;
PLL的参考时钟输入源包括:时钟输入管脚输入的时钟、PLL的参考时钟输入管脚输入的时钟,
全局时钟,区域时钟或I/O时钟以及来自内部逻辑的信号。其中PLL的参考时钟输入管脚可以让PLL获得最好的性能,强烈推荐用户使用。而来自内部逻辑的信号则容易受到内部其它信号的干扰,建议用户谨慎使用。
PLL的反馈时钟输入源可以分为PLL内部反馈和PLL外部反馈两种,其中PLL内部反馈时钟源是由专用的内部时钟构成。PLL的外部反馈时钟源包括:时钟输入管脚输入的时钟、PLL反馈时钟管脚输入、全局时钟,区域时钟或,I/O时钟以及来自内部逻辑的信号。其中来自内部逻辑信号则容易受到内部其它信号的干扰,建议用户使用PLL专用反馈时钟。 在本实验中,读者可以简单地理解为:外部时钟连接到具有时钟能力的输入引脚CCIO(Clock-Capable Input),进入PLL,产生不同频率和不同相位的时钟信号,然后驱动全局时钟资源。但是要进行更深入的FPGA开发,就必须理解器件的时钟资源架构。有关Logos时钟资源的更详细信息,读者后期可以花一些时间和精力去学习一下Logos官方的手册文档“Logos系列FPGA时钟资源(Clock)用户指南.pdf”里的介绍。
1.2 实验任务本节实验任务是使用ATK-DFPGL22G开发板的PLL IP输出5个不同时钟频率或相位的时钟,并使用PDS与Modelsim联合仿真以验证结果,最后生成比特流文件并将下载到开发板上,使用示波器来测量时钟的频率。
1.3 硬件设计本章实验将PLL IP核产生的5个时钟100MHz、100MHz_180deg、50MHz、25MHz、25MHz_75,连接到开发板的P3扩展口IO上,分别是第L0_D15_N、L0_D14_N、L0_D16_P、L0_D17_P、L0_D16_N号脚。扩展口原理图如下图所示: 本实验中,各端口信号的管脚分配如下表所示:
对应的FDC约束语句如下所示: - create_clock -name {clk} [get_ports {sys_clk}] -period{20} -waveform {0.000 10.000}
- define_attribute {p:sys_clk} {PAP_IO_DIRECTION} {INPUT}
- define_attribute {p:sys_clk} {PAP_IO_LOC} {B5}
- define_attribute {p:sys_clk} {PAP_IO_VCCIO} {3.3}
- define_attribute {p:sys_clk} {PAP_IO_STANDARD} {LVCMOS33}
- define_attribute {p:sys_clk} {PAP_IO_NONE} {TRUE}
- define_attribute {p:sys_rst_n} {PAP_IO_DIRECTION} {INPUT}
- define_attribute {p:sys_rst_n} {PAP_IO_LOC} {G5}
- define_attribute {p:sys_rst_n} {PAP_IO_VCCIO} {1.5}
- define_attribute {p:sys_rst_n} {PAP_IO_STANDARD} {LVCMOS15}
- define_attribute {p:sys_rst_n} {PAP_IO_NONE} {TRUE}
- define_attribute {p:clk_25m} {PAP_IO_DIRECTION} {OUTPUT}
- define_attribute {p:clk_25m} {PAP_IO_LOC} {G4}
- define_attribute {p:clk_25m} {PAP_IO_VCCIO} {3.3}
- define_attribute {p:clk_25m} {PAP_IO_STANDARD} {LVCMOS33}
- define_attribute {p:clk_25m} {PAP_IO_DRIVE} {4}
- define_attribute {p:clk_25m} {PAP_IO_NONE} {TRUE}
- define_attribute {p:clk_25m} {PAP_IO_SLEW} {SLOW}
- define_attribute {p:clk_25m_75} {PAP_IO_DIRECTION}{OUTPUT}
- define_attribute {p:clk_25m_75} {PAP_IO_LOC} {C2}
- define_attribute {p:clk_25m_75} {PAP_IO_VCCIO} {3.3}
- define_attribute {p:clk_25m_75} {PAP_IO_STANDARD}{LVCMOS33}
- define_attribute {p:clk_25m_75} {PAP_IO_DRIVE} {8}
- define_attribute {p:clk_25m_75} {PAP_IO_NONE} {TRUE}
- define_attribute {p:clk_25m_75} {PAP_IO_SLEW} {SLOW}
- define_attribute {p:clk_50m} {PAP_IO_DIRECTION} {OUTPUT}
- define_attribute {p:clk_50m} {PAP_IO_LOC} {C1}
- define_attribute {p:clk_50m} {PAP_IO_VCCIO} {3.3}
- define_attribute {p:clk_50m} {PAP_IO_STANDARD} {LVCMOS33}
- define_attribute {p:clk_50m} {PAP_IO_DRIVE} {4}
- define_attribute {p:clk_50m} {PAP_IO_NONE} {TRUE}
- define_attribute {p:clk_50m} {PAP_IO_SLEW} {SLOW}
- define_attribute {p:clk_100m} {PAP_IO_DIRECTION} {OUTPUT}
- define_attribute {p:clk_100m} {PAP_IO_LOC} {A1}
- define_attribute {p:clk_100m} {PAP_IO_VCCIO} {3.3}
- define_attribute {p:clk_100m} {PAP_IO_STANDARD}{LVCMOS33}
- define_attribute {p:clk_100m} {PAP_IO_DRIVE} {4}
- define_attribute {p:clk_100m} {PAP_IO_NONE} {TRUE}
- define_attribute {p:clk_100m} {PAP_IO_SLEW} {SLOW}
- define_attribute {p:clk_100m_180deg} {PAP_IO_DIRECTION}{OUTPUT}
- define_attribute {p:clk_100m_180deg} {PAP_IO_LOC} {A2}
- define_attribute {p:clk_100m_180deg} {PAP_IO_VCCIO} {3.3}
- define_attribute {p:clk_100m_180deg} {PAP_IO_STANDARD}{LVCMOS33}
- define_attribute {p:clk_100m_180deg} {PAP_IO_DRIVE} {4}
- define_attribute {p:clk_100m_180deg} {PAP_IO_NONE} {TRUE}
- define_attribute {p:clk_100m_180deg} {PAP_IO_SLEW} {SLOW}
复制代码
1.4 程序设计我们首先创建一个空的工程,工程名为“ip_pll”。接下来添加PLL IP核。在PDS软件的上方的菜单栏中“Tools”栏中单击“IP Compiler”按钮后弹出的“IP Compiler”窗口如图 17.4.2所示。 本实验使用的IP核路径是Module→PLL→PLL,如下图所示。 我们点击上图IP窗口下的“PLL (1.5)”IP核后,界面如下图所示。标签号为1处为指定例化此IP的路径,标签号为2处给新建的PLL IP核命名,本实验我们给新建的PLL IP命名为pll_clk,点击标签3处的“Customize”按钮是进入PLL IP参数配置页面。接下来的IP框里面的内容是该IP的基础信息,例如名称、版本号与所属公司(Pango)。Part框中的信息为工程所使用的芯片的详细信息,即选择器件类型,本实验选着的器件是“PGL22G-6CMBG324”。 点击上图中的“Customize”按钮进入“Customize IP”窗口对PLL的参数进行配置,“Customize IP”窗口界面如下图所示:图中的“Add IP”弹窗点击“Yes”。 图 17.4.6 “Customize IP”窗口 在选项卡Mode Selection界面有两个选项,一个是“Basic Configurations”基础配置模式,一个是“Advanced Configurations”高级配置模式。
1. Basic模式 Basic配置模式下,用户无需关心PLL的内部参数配置,只需输入期望的频率值、相位值、占空比等,软件平台自动计算,得到最佳的配置参数。如果没有特殊应用,建议使用Basic模式配置PLL。
2. Advanced模式 Advanced模式下,PLL的内部参数配置完全开放,用户需要根据应用需求自行计算相应配置参数,才能正确配置。Advanced模式下各个参数计算的详情用户可以参考《Logos系列产品PLL IP用户指南》(UG021001,Version1.5)。
本章实验只是PLL IP的基础使用,即使用默认的基础配置模式即可。
然后点击进入“Basic Configurations”选项卡界面,Basic模式界面主要包括输入配置(Input Configurations)、5个输出时钟配置(Clkout0~4 Configurations)与显示PLL内部设置参数(Show Internal Settings of PLL),Basic Configurations选项卡界面如下图所示: 图 17.4.7 Basic Configurations选项卡界面 把输入配置“Input Configurations”选项的输入时钟频率“Input Clock clkin1 Frequency”修改为我们开发板上的晶振频率50MHz,勾选“Enable Port pll_rst”复位使能信号,时钟IP核默认是高电平有效复位的。输入配置框其他的设置保持默认即可,时钟锁存信号(pll_lock)的作用是指示PLL输出的时钟信号是否稳定,当pll_lock拉高代表PLL输出时钟稳定,反之则表示输出不稳定或者错误。如下图所示。 图 17.4.8 “InputConfigurations”选项卡的设置 接下来输出时钟配置选项“Clkout0~4 Configurations”选项卡,在“Clkout Configurations”选项卡中,勾选5个时钟,并且将其“Desired Frequency”分别设置为100、100、50、25、25,注意,第2个100MHz时钟的相移“Desired Phase Shift”一栏要设置为180,第5个时钟的占空比“Desired Duty Cycle”设置为75.0%。其他设置保持默认即可,如下图所示。 图 17.4.9 “OutputClocks”选项卡的设置 勾选显示PLL内部设置参数(Show Internal Settings of PLL),“Internal Setting of PLL”框里面展示了对整个PLL的最终配置参数,这些参数都是根据之前用户输入的时钟需求由IPC(IP Compiler)来自动配置,PDS已经对参数进行了最优的配置,如下图所示。 至此本实验所需要的时钟已配置完成,接下来点击“Customize IP”窗口左上角的“Generate”在弹出的“Question”对话框选择“OK”即可,如下图所示。 点击“OK”后打印如下左图信息,至此时钟ip核配置成功,并生成pll_clk_tmpl.v文件。例化PLL IP时可以使用下图中pll_clk_tmpl.v文件红框中的代码。 然后如下图所示,关闭“Customize IP”页面与“IP Compiler”页面。 之后我们就可以在“Sources”窗口的“Designs”一栏中出现了该IP核“pll_clk”如下图所示。 我们接下来创建一个verilog源文件,其名称为ip_pll.v,代码如下: - 1 module ip_pll(
- 2 input sys_clk , //系统时钟
- 3 input sys_rst_n , //系统复位,低电平有效
- 4 //输出时钟
- 5 output clk_100m , //100Mhz时钟频率
- 6 output clk_100m_180deg, //100Mhz时钟频率,相位偏移180度
- 7 output clk_50m , //50Mhz时钟频率
- 8 output clk_25m , //25Mhz时钟频率
- 9 output clk_25m_75 , //25Mhz时钟频率,占空比75.0%
- 10 output locked
- 11 );
- 12
- 13 //锁相环
- 14 pll_clk u_pll_clk (
- 15 .pll_rst (~sys_rst_n ), // input
- 16 .clkin1 (sys_clk ), // input
- 17 .pll_lock (locked ), // output
- 18 .clkout0 (clk_100m ), // output
- 19 .clkout1 (clk_100m_180deg), // output
- 20 .clkout2 (clk_50m ), // output
- 21 .clkout3 (clk_25m ), // output
- 22 .clkout4 (clk_25m_75 ) // output
- 23 );
- 24
- 25 endmodule
复制代码程序中例化了pll_clk,把FPGA的系统时钟50Mhz连接到pll_clk的clkin1,系统复位信号连接到pll_clk的pll_rst,由于时钟IP核默认是高电平复位,而输入的系统复位信号sys_rst_n是低电平复位,因此要对系统复位信号进行取反。pll_clk输出的5个时钟信号直接连接到顶层端口的五个时钟输出信号。
我们接下来先对代码进行仿真,TestBench代码如下: - 1 module tb_ip_pll;
- 2
- 3 // Inputs
- 4 reg sys_clk;
- 5 reg sys_rst_n;
- 6
- 7 // Outputs
- 8 wire clk_100m;
- 9 wire clk_100m_180deg;
- 10 wire clk_50m;
- 11 wire clk_25m;
- 12 wire clk_25m_75;
- 13 wire locked;
- 14 //Instantiate the Unit Under Test (UUT)
- 15 ip_pll uut(
- 16 .sys_clk (sys_clk ), //系统时钟
- 17 .sys_rst_n (sys_rst_n ), //系统复位,低电平有效
- 18 //输出时钟
- 19 .clk_100m (clk_100m ), //100Mhz时钟频率
- 20 .clk_100m_180deg (clk_100m_180deg), //100Mhz时钟频率,相位偏移180度
- 21 .clk_50m (clk_50m ), //50Mhz时钟频率
- 22 .clk_25m (clk_25m ), //25Mhz时钟频率
- 23 .clk_25m_75 (clk_25m_75 ), //25Mhz时钟频率,占空比75.0%
- 24 .locked (locked )
- 25 );
- 26
- 27 initial begin
- 28 //Initialize Inputs
- 29 sys_clk = 0;
- 30 sys_rst_n = 0;
- 31
- 32 //Wait 100 ns for global reset to finish
- 33 #100;
- 34 sys_rst_n = 1;
- 35 //Add stimulus here
- 36 end
- 37
- 38 always #10 sys_clk=~sys_clk; //20ns
- 39
- 40 endmodule
复制代码对模块进行仿真的方法这里不再赘述,仿真后得到的波形如下图所示: 由上图可知,locked信号拉高之后,锁相环开始输出5个稳定的时钟。clk_100m和clk_100m_180deg周期都为10ns,即时钟频率都为100Mhz,但两个时钟相位偏移180度,所以这两个时钟刚好反相;clk_50m周期为20ns,时钟频率为50Mhz;clk_25m周期为40ns,时钟频率为25Mhz;clk_25m_75周期为40ns,时钟频率为25Mhz,占空比为75.0%。也就是说,我们创建的锁相环从仿真结果上来看是正确的。
1.5 下载验证
编译工程并生成比特流.sbit文件后,此时将下载器一端连接电脑,另一端与开发板上的JTAG下载口连接,连接电源线,并打开开发板的电源开关。
点击PDS工具栏的下载按钮,在弹出的Fabric Configuration界面中双击“Boundary Scan”,我们将生成好的sbit流文件下载到开发板中去。
程序下载完成后,接下来我们使用示波器测量开发板P3扩展口的第35、36、37、38、39号脚。示波器测试依次为A1(100MHz)、A2(100MHz_180)、C1(50MHz)、G4(25MHz)和C2(25MHz_75)。如下图所示: 此时在示波器上就可以观察到时钟的波形图。下图为使用示波器测量扩展口第38号脚(G4)所显示的波形。 图 17.5.2 扩展口G4脚(25MHz)输出的波形 由上图可知,示波器测量出的时钟频率为25Mhz,跟仿真结果是一样的,其它四个扩展口输出的时钟大家可以测试一下,这里不再贴出其它扩展口的波形图。 |