目录
实验任务:Vivado 下 IP核之 PLL实验
1、实验简介
2、实验环境
3、实验原理
3.1、PLL IP核简介
3.2、MMCM 和 PLL 各自的含义以及两者的区别
3.3、PLL 分频 和 倍频 的工作原理
3.4、实验任务
4、建立工程
4.1、PLL IP 核配置
4.2、模块设计
4.3、编写代码
4.4、Vivado 自带仿真器的使用
1、Vivado 自带仿真器的使用
《1》功能仿真需要的文件:
2、编写 TB 文件
4.5、仿真验证
4.6、知识扩展
不同仿真模式的区别
1、RTL 行为级仿真(功能仿真)
2、综合后门级功能仿真 (前仿真)
3、时序仿真 (后仿真)
小结
5、下载验证
5.1、添加引脚约束
5.2、上板验证
6、本章总结
7、拓展训练
实验任务:Vivado 下 IP核之 PLL实验
1、实验简介
PLL 的英文全称是 Phase Locked Loop,即锁相环,是一种反馈控制电路。PLL 对时钟网络进行系统级 的时钟管理和偏移控制,具有时钟倍频、分频、相位偏移和可编程占空比的功能。Xilinx 7 系列器件中的时 钟资源包含了时钟管理单元 CMT,每个 CMT 由一个 MMCM 和一个 PLL 组成。对于一个简单的设计来说, FPGA 整个系统使用一个时钟或者通过编写代码的方式对时钟进行分频是可以完成的,但是对于稍微复杂一 点的系统来说,系统中往往需要使用多个时钟和时钟相位的偏移,且通过编写代码输出的时钟无法实现时 钟的倍频,因此学习 Xilinx MMCM/PLL IP 核的使用方法是我们学习 FPGA 的一个重要内容。本章我们将通 过一个简单的例程来向大家介绍 MMCM/PLL IP 核的使用方法。
很多初学者看到板上只有一个 200Mhz 时钟输入的时候都产生疑惑,如果要工作在 100Mhz、150Mhz 怎么办?在很多 FPGA 芯片内部都集成了 PLL,其他厂商可能不叫 PLL,但是也有类似的功能模块,通过 PLL 可以倍频分频,产生其他很多时钟。本实验通过调用 PLL ip core 来学习 PLL 的使用、vivado 的 IP core 使用方法。
本实验基于 Xinlinx 黑金 AX7A035t FPGA 开发板,输出 4 个不同时钟频率或相位的时钟,并在 Vivado 中进行仿真以验证结果,最后生成比特流文件并将下载到开发板上,使用示波器来测量时钟的频率。
2、实验环境
- Windows 10 64 位
- vivado 2020.2
- Xinlinx 黑金 FPGA 开发板(AX7A035t 开发板、AX7A100t 开发板、AX7A200t 开发板)
- 示波器
3、实验原理
3.1、PLL IP核简介
锁相环作为一种反馈控制电路,其特点是利用外部输入的参考信号来控制环路内部震荡信号的频率和 相位。因为锁相环可以实现输出信号频率对输入信号频率的自动跟踪,所以锁相环通常用于闭环跟踪电路。 锁相环在工作的过程中,当输出信号的频率与输入信号的频率相等时,输出电压与输入电压保持固定的相 位差值,即输出电压与输入电压的相位被锁住,这就是锁相环名称的由来。
锁相环拥有强大的性能,可以对输入到 FPGA 的时钟信号进行任意分频、倍频、相位调整、占空比调整,从而输出一个期望时钟;除此之外,在一些复杂的工程中,哪怕我们不需要修改任何时钟参数,也常常会使用 PLL 来优化时钟抖动,以此得到一个更为稳定的时钟信号。正是因为 PLL 的这些性能都是我们在实 际设计中所需要的,并且是通过编写代码无法实现的,所以 PLL IP 核才会成为程序设计中最常用 IP 核之 一。
需要注意的是:Xilinx 中的 PLL 是模拟锁相环,其优点是输出的稳定度高、锁定时间较短,相位连续可 调;缺点是在极端环境(例如极端高/低温环境,高磁场强度等)下容易失锁。
Xilinx7 系列器件中的时钟资源包含了时钟管理单元 CMT(全称 Clock Management Tile,即时钟管理单 元),每个 CMT 由一个 MMCM(全称 Mixed-Mode Clock Manager,即混合模式时钟管理)和一个 PLL(全 称 Phase Locked Loop,即锁相环)组成,Xilinx 7 系列器件中具有时钟管理单元 CMT 时钟资源,xc7a35t 芯片内部有 5 个 CMT,xc7a100t 芯片 内部有 6 个 CMT,xc7a200t 芯片内部有 10 个 CMT,为设备提供强大的系统时钟管理以及高速 I/O 通信的能力。为设备提供强大的系统时钟管理以及高速 I/O 通信的能力。
3.2、MMCM 和 PLL 各自的含义以及两者的区别
接下来我们讲解一下 MMCM 和 PLL 各自的含义以及两者的区别:
(1)PLL:为锁相回路或锁相环,用来统一整合时钟信号,使高频器件正常工作,如内存的存取数据 等。PLL 用于振荡器中的反馈技术。
(2)MMCM(混合模式时钟管理):是基于 PLL 的新型混合模式时钟管理器,实现了最低的抖动和抖 动滤波,为高性能的 FPGA 设计提供更高性能的时钟管理功能。
(3)MMCM 是一个 PLL 上加入 DCM 的一部分以进行精细的相移,也就是说 MMCM 在 PLL 的基础 上加上了相位动态调整功能,又因为 PLL 是模拟电路,而动态调相是数字电路,所以 MMCM 被称为混合 模式,MMCM 相对 PLL 的优势就是相位可以动态调整,但 PLL 占用的面积更小,而在大部分的设计当中大家使用 MMCM 或者 PLL 来对系统时钟进行分频、倍频和相位偏移都是完全可以的。
MMCM/PLL 的参考时钟输入可以是 IBUFG(CC)即具有时钟能力的 IO 输入、区域时钟 BUFR、全局时钟 BUFG、GT 收发器输出时钟、行时钟 BUFH 以及本地布线(不推荐使用本地布线来驱动时钟资源)。在最多的情况下,MMCM/PLL 的参考时钟输入都是来自 IBUFG(CC)即具有时钟能力的 IO 输入,本实验也是如此。MMCM/PLL 的输出可以驱动全局时钟 BUFG 和行时钟 BUFH 等等。BUFG 能够驱动整个器件内部的通用逻辑的所有时序单元的时钟端口。
接着我们讲一下 PLL 的工作原理,首先我们画出一个大致的结构模型示意图,如下图所示:
由上图可以看出 PLL 的工作流程如下:
1、通过 PFD(全称:Phase-Frequency Detector,即鉴频鉴相器)对参考时钟(ref_clk)频率和需要比较的时钟频率(即上图中的输出时钟:pll_out)进行对比。
2、PFD 的输出连接到 LF(全称:Loop Filter,即环路滤波器)上,用于控制噪声的带宽,滤掉高频噪声,使之趋于一个稳定的值,起到将带有噪声的波形变平滑的作用。如果 PFD 之前的波形抖动比较大,经过环路滤波器后抖动就会变小,趋近于信号的平均值。
3、经过 LF 的输出连接到 VCO(全称:Voltage Controlled Oscillator,即压控振荡器)上,LF 输出的电压可以控制 VCO 输出频率的大小,LF 输出的电压越大 VCO 输出的频率越高,然后将这个频率信号连接到 PFD 作为需要比较的频率。
如果参考时钟输入的频率和需要比较的时钟频率不相等,该系统最终实现的就是让它们逐渐相等并稳定下来。例如参考时钟的频率是50MHz,经过整个闭环反馈系统后,锁相环对外输出的时钟频率也是50MHz。
参考时钟可以类比为道路的方向,需要比较的时钟可以类比为汽车的行驶方向,人眼就是鉴频鉴相器,大脑就相当于滤波器,方向盘就相当于 VCO。人眼检测道路方向和行驶方向是否有偏差,大脑对方向偏差做出判断(偏左、偏右或无偏差),并将判断结果转换为方向盘的动作(左打、右打或不变),然后将调整后的行驶方向与道路方向再次通过人眼进行对比,经过反复的对比和调整后,最终使得行驶方向与道路方向一致。
3.3、PLL 分频 和 倍频 的工作原理
接下来我们讲解一下 PLL 分频和倍频的工作原理,PLL 分频原理图如下图所示:
分频是在参考时钟与 PFD 之间加入一级分频器(可称为前置分频器),通过前置分频器 N(N 表示数字) 分频后得到一个新的参考时钟,因此需要比较的时钟频率(即 pll_out)就始终是和新的参考时钟频率进行对比的,pll_out 的输出结果也会逐渐与新的参考时钟(ref_clk/N)相等,从而实现了分频的功能。 PLL 倍频原理图如下图所示:
倍频是在 VCO 与 PFD 之间加入一级分频器(可称为后置分频器),通过后置分频器 M(M 表示数字)分频后得到一个新的需要比较的时钟频率(即 pll_out 分频后的时钟),因为此时与参考时钟频率进行对比的是分频后的输出时钟(pll_out/M),所以此时的输出时钟是参考时钟的 M 倍(pll_out = ref_clk * M),从而实现了倍频的功能。
需要注意的是,一个 PLL IP 核输出的时钟路数是有限的,且输入/输出的时钟频率也是有限制的,我们不能无限制的输入无穷大/小的时钟频率,也不可能通过倍频或分频输出无穷大/小的时钟频率。
MMCM(Mixed-Mode Clock Manager)混合模式时钟管理器,MMCM 功能是 PLL 的超集,它是在 PLL 的基础上加了相位动态调整功能,PLL 是模拟的,而动态调相是数字电路,所以称为混合模式。其相对于PLL 的优势是相位可以动态调整,占用面积较大。MMCM 主要用于驱动器件逻辑(CLB、DSP、RAM 等)的时钟。PLL 是和 IO 资源紧密绑定的,占用面积小,常用于为内存接口生成所需的时钟信号,但也具有与 其他器件逻辑的连接,因此如果需要额外的功能,它们可以用作额外的时钟资源。关于 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)/(D*O)。
Xilinx 提供了用于实现时钟功能的 IP 核 Clocking Wizard,该 IP 核能够根据用户的时钟需求自动配置器 件内部的 CMT,以实现用户的时钟需求。
想了解更多的时钟资源, 建议大家看看 Xilinx 提供的文档 “7 Series FPGAs Clocking Resources User Guide”。
在本实验中,读者可以简单地理解为:外部时钟连接到具有时钟能力的输入引脚 CCIO(Clock-Capable Input),进入 MMCM/PLL,产生不同频率和不同相位的时钟信号,然后驱动全局时钟资源 BUFG。
3.4、实验任务
本节实验的任务是使用开发板输出 4 个不同频率或相位的时钟,四个时钟分别为一个倍频时钟 (100MHz),一个倍频后相位偏移 180 度的时钟(100MHz),一个与系统时钟相同的时钟(50MHz)和 一个分频时钟(25MHz),并在 Vivado 中进行仿真以验证结果,最后生成比特流文件并下载到开发板 上,使用示波器来测量时钟的频率是否正确。
4、建立工程
本实验中为大家演示如果调用 Xilinx 提供的 PLL IP 核来产生不同频率的时钟,并把其中的一个时钟输出到 FPGA 外部 IO 上,也就是 AX7A035 开发板 J11 的 PIN3 脚,AX7A100/AX7A200 开发板 J13 的 PIN3 脚。
下面为程序设计的详细步骤:
4.1、PLL IP 核配置
首先我们创建一个名为“ip_clk_wiz”的空工程,然后点击 Vivado 软件左侧“Flow Navigator”栏中的 “IP Catalog”,如下图所示:
点击“IP Catalog”后弹出的“IP Catalog”窗口如下图所示:
打开“IP Catalog”窗口后,在搜索栏中输入“clock”关键字,可以看到 Vivado 已经自动查找出了与关键字匹配的 IP 核名称,如下图所示:
我们双击“FPGA Features and Design”→“Clocking”下的“Clocking Wizard”,弹出“Customize IP”窗口,如下图所示:
最上面的“Component Name”一栏可以设置该 IP 元件的名称,这里我们保持默认命名,当然也可以命名为其它方便自己一眼看出其功能的名称。
需要说明的是,这里以 PLL IP 核为例,当大家是第一次使用某个 IP 核时,如果想要了解这个 IP 核的使用和相关参数定义的话,可以点击 Documentation 下的 Product Guide 来打开这个 IP 核的产品指南。因为本章主要讲解 PLL IP 核的使用,很多我们不需要进行修改的参数在文档中可能就一句话带过了,所以如果 大家想详细的了解各个配置参数的含义的话,就可以打开这篇产品指南来进行深入学习。
接下来就是配置 IP 核的时钟参数了,第一个“Clocking Options”选项卡的参数配置如下所示:
在第一个“Clocking Options”选项卡中,各参数(大家可以重点关注(6)中内容)含义如下:(1)、“Clock Monitor”用来监控时钟是否停止、故障和频率变化。我们一般不用,所以不做勾选。
(2)、“Primitive”选项用于选择是使用 MMCM 还是 PLL 来完成时钟需求,对于我们的本次实验来 说,MMCM 和 PLL 都可以完成,但是本章实验的目的是掌握 PLL IP 核的使用,所以这里我们选择 PLL。
(3)、“Clocking Featurs”用来设置时钟的特征,包括 Frequency Synthesis(频率合成)、Minimize Power(最小化功率)、Phase Alignment(相位校准)、Dynamic Reconfig(动态重配置)、Safe Clock Startup(安全时钟启动)等,另外 Spread Spectrum(扩频)和 Dynamic Phase Shift(动态相移)是使用 MMCM 时才能够设置的特征,这里我们保持默认的设置即可,感兴趣的同学也可以勾选其它选项来观察会有什么不同效果。
(4)、“Jitter Optimization”用于抖动优化(可选平衡,最小化输出抖动或最大化输出抖动等优化方 式),这里我们保持默认平衡优化方式即可。
(5)、“Dynamic Reconfig Interface Options”用于选择动态重构接口,只有在设置时钟的特征时勾选 动态重构选项后方可进行配置。
(6)、“Input Clock Information”下的表格用于设置输入时钟的信息,其中: 第一列“Input Clock(输入时钟)”中 Primary(主要,即主时钟)是必要的,Secondary(次要,即副 时钟)是可选是否使用的,若使用了副时钟则会引入一个时钟选择信号(clk_in_sel),需要注意的是主副时 钟不是同时生效的,我们可以通过控制 clk_in_sel 的高低电平来选择使用哪一个时钟,当 clk_in_sel 为 1 时 选择主时钟,当 clk_in_sel 为 0 时选择副时钟。这里我们只需要用到一个输入时钟,所以保持默认不启用副时钟。
第二列“Port Name(端口名称)”可以对输入时钟的端口进行命名,这里我们可以保持默认的命名。
第三列“lnput Frequency(输入频率)”可以设置输入信号的时钟频率,单位为 MHz,主时钟可配置的输入时钟范围(19MHz~800MHz)可以在其后面的方块中进行查看;副时钟可配置的时钟输入范围会随着主时钟的频率而有所改变,具体范围同样可以在其后面的方块中进行查看。因为我们的我们开发板上的晶振频率为 200MHz,所以我们将主时钟的时钟频率设置为 200。
第四列“Jitter Options(抖动选项)”有 UI(百分比)和 PS(皮秒)两种表示单位可选。
第五列“lnput Jitter(输入抖动)”为设置时钟上升沿和下降沿的时间,例如输入时钟为 50MHz,Jitter Options 选择 UI,lnput Jitter 输入 0.01,择上升沿和下降沿的时间不超过 0.2ns(20ns*1%),若此时将 UI 改 为 PS,则 0.01 会自动变成 200(0.2ns=200ps)。
第六列“Source(来源)”中有四种选项:
1、“Single ended clock capable pin(支持单端时钟引脚)”,当输入的时钟来自于单端时钟引脚时,需要选择这个。如果系统时钟就是由晶振产生并通过单端时钟引脚接入的,就选择 “Single ended clock capable pin”。
2、“Differential clock capable pin(支持差分时钟引脚)”,当输入的时钟来自于差分时钟引脚时,需要选择这个。因为本次实验的系统时钟就是由差分晶振产生的,所以这里我们选择 “Differential clock capable pin”。(AX7A035 核心板上配有两个 Sitime 公司的有源差分晶振,一个是 200MHz,型 号为 SiT9102-200.00MHz,用于 FPGA 的系统主时钟和用于产生 DDR3 控制时钟;另 一个为 125MHz,型号为 SiT9102-125MHz,用于 GTP 收发器的参考时钟输入。 )
3、“Global buffer(全局缓冲器)”,输入时钟只要在全局时钟网络上,就需要选择这个。例如前一个 PLL IP 核的输出时钟接到后一个 PLL IP 核的输入时,只要前一个 PLL 输出的时钟不是“No buffer”类型即可。
4、“No buffer(无缓冲器)”,输入时钟必须经过全局时钟缓冲器(BUFG),才可以选择这个。例如 前一个 PLL IP 核的输出时钟接到后一个 PLL IP 核的输入时,前一个 PLL 输出的时钟必须为 BUFG 或者 BUFGCE 类型才可以。
接下来切换至“Output Clocks”选项卡,该选项卡中的参数配置如下:
在“Output Clock”选项卡中,各参数(大家可以重点关注(1)中的内容)含义如下:
(1)、The phase is calculated relative to the active input clock 表格用于设置输出时钟的路数(一个 PLL IP 核最多可输出六路不同频率的时钟信号)及参数,其中:
第一列“Output Clock”为设置输出时钟的路数,因为我们需要输出四路时钟,所以勾选前 4 个时钟。
第二列“Port Name”为设置时钟的名字,这里我们可以保持默认的命名。
第三列“Output Freq(MHz)”为设置输出时钟的频率,这里我们要对“Requested(即理想值)”进行设 置,我们将四路时钟的输出频率分别设为 100、100、50 和 25,设置完理想值后,我们就可以在“Actual” 下看到其对应的实际输出频率。需要注意的是 PLLIP 核的时钟输出范围为 6.25MHz~800MHz,但这个范围 是一个整体范围,根据驱动器类型的选择不同,其所支持的最大输出频率也会有所差异。
第四列“Phase (degrees)”为设置时钟的相位偏移,同样的我们只需要设置理想值,这里我们将第二路 100MHz 的时钟输出信号的相位偏移设置为 180,其余三路信号不做相位偏移处理。
第五列“Duty cycle”为占空比,正常情况下如果没有特殊要求的话,占空比一般都是设置为 50%,所 以这里我们保持默认的设置即可。
第六列“Drives”为驱动器类型,有五种驱动器类型可选: BUFG 是全局缓冲器,如果时钟信号要走全局时钟网络,必须通过 BUFG 来驱动,BUFG 可以驱动所有的 CLB,RAM,IOB。本次实验我们保持默认选项 BUFG。
BUFH 是区域水平缓冲器,BUFH 可以驱动其水平区域内的所有 CLB,RAM,IOB。 BUFGCE 是带有时钟使能端的全局缓冲器,它有一个输入端 I、一个使能端 CE 和一个输出端 O。只有当 BUFGCE 的使能端 CE 有效(高电平)时,BUFGCE 才有输出。
BUFHCE 是带有时钟使能端的区域水平缓冲器,用法与 BUFGCE 类似。
No buffer 即无缓冲器,当输出时钟无需挂在全局时钟网络上时,可以选择无缓冲区。
第七列“Max Freq of buffer”为缓冲器的最大频率,例如我们选取的 BUFG 缓冲器支持的最大输出频率 为 464.037MHz。
(2)、USE CLOCK SEQUENCING(使用时钟排序),当在第一个选项卡上启用安全时钟启动功能时, Use Clock Sequence 表处于活动状态,可用于配置每个已启用时钟的序列号。在此模式下,只允许 BUFGCE 作为时钟输出的驱动程序。
(3)、Clocking Feedback(时钟反馈),用于设置时钟信号的来源是片上还是片外,是自动控制还是 用户控制,当自动控制片外的时钟时,还需要配置时钟信号的传递方式是单端还是差分,这里我们保持默认 选项(自动控制片上)即可。
(4)、Enable Optional lnputs/Outputs for MMCM/PLL(启用 MMCM/PLL 的可选输入/输出),其中 reset(复位)和 power_down(休眠)为输入信号,locked(锁定)为输出信号,因为我们不需要锁相环进入休眠状态,所以这里我们保持默认启用复位信号和锁定信号即可。
(5)、Reset Type(复位类型),用于设置复位信号是高电平有效还是低电平有效,这里我们可以保持默认的高电平有效。
接着我们来到“Port Renaming”选项卡,如下图所示
“Port Renaming” 选项卡主要是对一些控制信号(复位信号以外的信号)的重命名。在上一个选项卡 中我们启用了锁定信号 locked,因此这里我们只看到了 locked 这一个可以重命名的信号,因为默认的名称 已经可以让我们一眼看出该信号的含义,所以无需重命名,保持默认即可。
“PLLE2 Setting” 选项卡展示了对整个 PLL 的最终配置参数,这些参数都是由 Vivado 根据之前用户 输入的时钟需求来自动配置的,Vivado 已经对参数进行了最优的配置,在绝大多数情况下都不需要用户对它们进行更改,也不建议更改,所以这一步保持默认即可,如下图所示
最后的“Summary”选项卡是对前面所有配置的一个总结,在检查没问题后我们点击“OK”按钮,如 下图所示:
接着就弹出了“Generate Output Products”窗口,我们直接点击“Generate”即可,如下图所示:
之后我们就可以在“Design Runs”窗口的“Out-of-Context Module Runs”一栏中看到该 IP 核对应的 run“clk_wiz_0_synth_1”,其综合过程独立于顶层设计的综合,所以此时我们可以看到其正在综合,如下图所示:
在其 Out-of-Context 综合的过程中,我们就可以开始编写代码来调用我们设置好的 IP 核了,有关 代码部分的讲解,请看下一小节的内容。
4.2、模块设计
本次实验的目的是通过 PLL IP 核输出四路不同频率或相位的时钟,因此给模块命名为 ip_clk_wiz。首 先想要输出四路不同频率或相位的时钟,就需要输入一个基准时钟,因此实验需要用到系统时钟;其次为了使程序能恢复至默认状态,系统复位在 FPGA 系统中也是必不可少的;由此可以分析出,本次实验需要系统时钟和系统复位这两个输入端口,以及四个时钟输出端口,经分析画出模块框图如下所示:
模块端口与功能描述如下表所示:
我们开发板的系统时钟为 200MHz,即一个时钟周期为 5ns。100MHz 的时钟一个时钟周期为 10ns; 100MHz 相位偏移 180°的时钟就相当于将 100MHz 的时钟的高低电平变化做了一个反相处理;50MHz 的时钟一个时钟周期为 20ns;25MHz 的时钟一个时钟周期为 40ns。
需要注意的是,PLL IP 核会输出一个时钟锁定 信号(locked),所有通过 PLL IP 核产生的时钟都是在 locked 为高电平(即时钟已锁定)时才会输出稳定 的时钟信号。
这里需要说明一点,在时钟锁定信号(locked)拉高之前,时钟信号是不稳定,既可能是高电平,也 可能是低电平,还可能是不稳定的时钟信号(用示波器或频谱仪可以看到是飘忽不定的),这里绘制时就 以低电平来涵盖了。
4.3、编写代码
首先打开 IP 核的例化模板,在“Source”窗口中的“IP Sources”选项卡中,依次用鼠标单击展开“IP”-“clk_wiz_0”-“Instantitation Template”后,我们可以看到“clk_wiz.veo”文件,它是由 IP 核自动生成的只读的 verilog 例化模板文件,双击就可以打开它,在例化时钟 IP 核模块的时候,可以直接从这里拷贝,如 下图所示:
接下来我们创建一个 verilog 源文件,其名称为 ip_clk_wiz.v,代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/05/13 16:14:57
// Design Name:
// Module Name: ip_clk_wiz
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
//PLL的英文全称是Phase Locked Loop,即锁相环,是一种反馈控制电路。
//PLL对时钟网络进行系统级的时钟管理和偏移控制,具有时钟倍频、分频、相位偏移和可编程占空比的功能。
//实验任务:IP核之 PLL实验
//本节实验任务是使用Xinlinx 黑金 FPGA 开发板输出 4 个不同时钟频率或相位的时钟,
//并在 Vivado 中进行仿真以验证结果,最后生成比特流文件并将下载到开发板上,
//使用示波器来测量时钟的频率。
module ip_clk_wiz(
// input sys_clk, //50MHz系统时钟
//***********差分时钟系统*****************************************
input sys_clk_p, // Differential input clock 200Mhz
input sys_clk_n, // Differential input clock 200Mhz
//***********差分时钟系统*****************************************
input sys_rst_n, //系统复位,低电平有效
//输出时钟
output clk_out1, //100Mhz时钟频率
output clk_out2, //100Mhz时钟频率,相位偏移180度
output clk_out3, //50Mhz时钟频率
output clk_out4 //25Mhz时钟频率
);
//*****************************************************
//** main code
//*****************************************************
wire locked;
//MMCM/PLL IP核的例化
clk_wiz_0 clk_wiz_0
(
// Clock out ports
.clk_out1 (clk_out1), // output clk_out1_100m
.clk_out2 (clk_out2), // output clk_out2_100m_180
.clk_out3 (clk_out3), // output clk_out3_50m
.clk_out4 (clk_out4), // 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
.clk_in1_p (sys_clk_p), // input clk_in1_p
.clk_in1_n (sys_clk_n) // input clk_in1_n
);
endmodule
程序中例化了 clk_wiz_0,把 FPGA 的系统时钟 50Mhz 连接到 clk_wiz_0 的 clk_in1,系统复位信号连接 到 clk_wiz_0 的 reset,由于配置时钟 IP 核时我们保持了默认的高电平复位,而输入的系统复位信号 sys_rst_n 是低电平复位,因此要对系统复位信号进行取反。clk_wiz_0 输出的 4 个时钟信号直接连接到顶层端口的四 个时钟输出信号。
4.4、Vivado 自带仿真器的使用
1、Vivado 自带仿真器的使用
Vivado 设计套件内部集成了仿真器 Vivado Simulator,能够在设计流程的不同阶段运行设计的功能仿真和时序仿真,结果可以在 Vivado IDE 集成的波形查看器中显示。Vivado 还支持与诸如 ModelSim、Verilog Compiler Simulator (VCS)、Questa Advanced Simulator 等第三方仿真器的联合仿真。
《1》功能仿真需要的文件:
1.设计 HDL 源代码:可以是 VHDL 语言或 Verilog 语言。
2.测试激励代码(TestBench):根据设计要求输入/输出激励,由于不需要进行综合,书写具有很大的灵活性。
3.仿真模型/库:根据设计内调用的器件供应商提供的模块而定,如:FIFO、ADD_SUB 等。在使用 Vivado Simulator 时,仿真器所需的仿真模型/库是预编译好并集成在 Vivado 中的,因此不需要进行额外的预编译操作,直接加载 HDL 设计和 TestBench 即可执行仿真。
2、编写 TB 文件
我们接下来先对代码进行仿真,因为本章实验我们只有系统时钟和系统复位这两个输入信号,所以仿真 文件也只需要编写这两个信号的激励即可。
接下来我们开始在 Vivado IDE 中进行仿真,首先创建/添加一个 TestBench。我们点击“Sources”窗口 中的“+”号(Add Sources 命令),在弹出的窗口中选择“Add or Create Simulation Sources”,如图 22.5.2 和图 22.5.3 所示:
点击 next,若我们还没有编写仿真代码,则可以点击“Create File”来创建仿真源文件,创建的流程和创建 verliog 源文件相同,这里就不再赘述了,感兴趣的同学可以自行尝试看看。仿真文件名为“tb_ip_clk_wiz”,TestBench 代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/05/13 16:17:11
// Design Name:
// Module Name: tb_ip_clk_wiz
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb_ip_clk_wiz();
//parameter T = 20; //50MHz时钟周期为20ns
parameter T = 5; //200MHz时钟周期为5ns
//reg sys_clk;
//***********差分时钟系统*****************************************
reg sys_clk_p;
wire sys_clk_n;
//***********差分时钟系统*****************************************
reg sys_rst_n;
wire clk_out1;
wire clk_out2;
wire clk_out3;
wire clk_out4;
//always #10 sys_clk = ~sys_clk;
always #(T/2) sys_clk_p = ~ sys_clk_p; //5ns一个周期,产生200MHz时钟源
assign sys_clk_n = ~ sys_clk_p;
initial begin
// sys_clk = 1'b0;
sys_clk_p = 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_clk_p (sys_clk_p ),
.sys_clk_n (sys_clk_n ),
.sys_rst_n (sys_rst_n ),
.clk_out1 (clk_out1 ),
.clk_out2 (clk_out2 ),
.clk_out3 (clk_out3 ),
.clk_out4 (clk_out4 )
);
endmodule
然后在“Flow Navigator”窗口中点击“Run Simulation”并选择“Run Behavioral Simulation”,如下图所示:
经过稍许时间的等待,我们就进入了 Vivado 自带的仿真器界面,如下图所示:
下面分别介绍仿真界面中的各个子窗口:
(1)“Scope”窗口:“Scope”是 HDL 设计的层次划分。在“Scope”窗口中,我们可以看到设计的层次结构。当大家选择了一个“Scope”层次结构中的作用域时,该作用域内的所有 HDL 对象,包括 reg、 wire 等都会出现在“Objects”窗口中。大家可以在“Objects”窗口中选择 HDL 对象,并将它们添加到波形查看器中。
(2)“Object”窗口:“Objects”窗口会显示在“Scopes”窗口中选择的范围内的所有 HDL 仿真对象。 例如,我们在“Scope”窗口中选择顶层模块“ip_clk_wiz”,在“Objects”窗口中就会自动显示出“ip_clk_wiz” 模块中所有的 HDL 仿真对象。如下图所示:
可以看出,在“ip_clk_wiz”顶层模块中除了顶层端口 sys_clk、sys_rst_n 和四路时钟输出之外,还包括 在内部定义的时钟锁定信号(locked)。
(3)波形窗口:用于显示所要观察信号的波形。若要向波形窗口添加单个 HDL 对象或多个 HDL 对象, 可以在“Objects”窗口中,右键单击一个或多个对象,然后从下拉菜单中选择“Add to Wave Window”选项。
例如:我们把“ip_clk_wiz”模块下的“locked”信号添加到波形窗口中,如下图所示:
添加到波形窗口中的“locked”信号如下图所示:
我们可以将信号任意的上下拖动,并放置在方便我们观察的位置,在绘制波形图时我们曾说过“locked 为高电平(即时钟已锁定)时才会输出稳定的时钟信号”,所以为了方便观察,这里我们将“locked”信号拖动到四路时钟输出信号的上方,如下图所示:
图 22.5.13 将“locked”信号拖动至方便观查的位置
一般来说,每当我们进行一次仿真时,都会把当前波形的配置信息保存下来,包括波形窗口中具有哪些信号等等,以便在下一次打开仿真器进行仿真时,继续使用上一次仿真的配置信息。我们点击波形窗口中的保存按钮,如下图所示:
之后会弹出“Save Waveform”对话框,提示用户将当前波形配置信息保存为“.wcfg”后缀的文件,且 工具已经自动地输入了文件名“tb_ip_clk_wiz_behav”,文件的保存目录也被工具自动设置为了当前的工程目录,所以我们保持其默认即可,直接点击“Save”。如下图所示:
这里有个地方需要大家注意下,wcfg 文件只是包含波形窗口的配置信息,并不包含波形的数据文件。 在点击保存后会弹出一个消息框,询问用户是否将刚刚创建的“tb_ip_clk_wiz_behav.wcfg”文件添加到当前工程中,我们直接点击“Yes”即可。如下图所示:
(4)仿真工具栏:仿真工具栏包含运行各个仿真动作的命令按钮。从左至右依次是:
• Restart:将仿真时间重置为零,此时波形窗口中原有的波形都会被清除。下次执行仿真时,会从 0 时刻重新开始。
• Run all:运行仿真,直到其完成所有事件或遇到 HDL 语句中的$stop 或$finish 命令为止。注意,如果没有在 TestBench 语句中加入$stop 或$finish 命令,当点击 Run all 命令时,仿真器会无休止地一直仿真下去,除非用户点击仿真工具栏中的“Break”按钮来手动地结束仿真。但是这里有个地方需要注意,如果此时需要仿真的设计比较复杂,则仿真器在运行仿真时会耗费电脑大量的 CPU 和内存资源,此时有可能会造成电脑卡顿甚至死机的情况。所以,如果设计比较复杂,且没有在 TestBench 语句中加入$stop 或$finish 命令,
最好不要轻易点击 Run all 命令。
• Run For:运行特定的一段时间。紧随在后面的两个文本框用于设定仿真时长的数值大小和时间单位。
• Step:按步运行仿真,每一步仿真一个 HDL 语句。
• Break:暂停当前仿真。
• Relaunch:重新编译仿真源并重新启动仿真。在使用 Vivado 仿真器来调试 HDL 设计时,我们可能会根据仿真结果来对自己的 HDL 源代码进行修改。在修改完 HDL 源代码后,可以点击 Relaunch 按钮来重新加载 UUT 设计和 TestBench,以重新对修改后的 HDL 源代码进行仿真。此时就不需要再关闭并重新打开仿真器了。
介绍完各个窗口和命令按钮的使用后,我们就可以开始仿真了。在刚打开仿真器时,仿真器会首先将 TestBench 中的信号加入到波形窗口中,并执行一段时长的仿真,仿真的时长由 Settings 设置窗口中的参数值指定,如下图所示:
可以看到,仿真器启动后默认立即执行的仿真时长是 1000ns。由于我们是在默认立即执行仿真结束之后,才加入了“locked”信号,所以新加入的“locked”信号并没有波形显示。此时我们需要将仿真时刻重置为 0,重新开始仿真。点击“Restart”按钮后,波形窗口中的当前仿真时刻点(黄色标尺)就会回归到 0 时刻,且原先的所有波形都被清除,如下图所示:
这时我们点击仿真工具栏中的“Run For”按钮,默认仿真时长是 10us,如下图所示:
此时波形虽然显示完全了,但是由于太过密集导致不便于我们对其进行观察,为了能清楚的观察到信号的变化,首先我们可以将仿真时刻点(黄色标尺)移动到“locked”信号的上升沿位置,因为四路输出时钟在“locked”信号为高电平时才会稳定输出,然后按住“Ctrl”键并滚动鼠标滚轮,就可以放大/缩小波形了。
4.5、仿真验证
由上图可知,locked 信号拉高之后,锁相环开始输出 4 个稳定的时钟。clk_100m 和 clk_100m_180deg周期都为 10ns,即时钟频率都为 100Mhz,但其中 clk_100m_180deg 相对于系统时钟相位偏移了 180 度;clk_50m 周期为 20ns,即时钟频率为 50Mhz;clk_25m 周期为 40ns,即时钟频率为 25Mhz。也就是说,我们创建的锁相环从仿真结果上来看是正确的。
4.6、知识扩展
如上图所示,Vivado 有如下五种仿真模式:
1、“run behavioral simulation”行为级仿真,也是通常说的功能仿真。
2、“post-synthesis function simulation”综合后的功能仿真。
3、“post-synthesis timing simulation”综合后的时序仿真,和真实运行的时序就相差不远了。
4、“post-implementation function simulation”实现后的功能仿真。
5、“post-implementation timing simulation”实现后的时序仿真,最接近真实的时序波形。
不同仿真模式的区别
数字电路设计中一般包括 3 个大的阶段:源代码输入、综合和实现,而电路仿真的切入点也基本与这些阶段相吻合,根据不同的设计阶段,仿真可以分为 RTL 行为级仿真、综合后门级功能仿真和时序仿真, 具体描述如下:
1、RTL 行为级仿真(功能仿真)
在大部分设计中执行的第一个仿真都是 RTL 行为级仿真。这个阶段的仿真可以用来检查代码中的语法错误以及代码行为的正确性,需要注意是该阶段的仿真是不包含延时信息的。如果没有实例化一些与器件相关的特殊底层元件的话,这个阶段的仿真也可以做到与器件无关。因此在设计的初期阶段不使用特殊底层元件即可以提高代码的可读性、可维护性,又可以提高仿真效率,且容易被重用。(绝大部分设计人员将这个阶段的仿真叫做功能仿真!)
2、综合后门级功能仿真 (前仿真)
一般在设计流程中的第二个仿真是综合后门级功能仿真。绝大多数的综合工具除了可以输出一个标准网表文件以外,还可以输出 Verilog 或者 VHDL 网表,其中标准网表文件是用来在各个工具之间传递设计数据的,并不能用来做仿真使用,而输出的 Verilog 或者 VHDL 网表是可以用来仿真的。之所以叫门级仿真是因为综合工具给出的仿真网表已经是与生产厂家的器件的底层元件模型对应起来了,所以为了进行综合后仿真必须在仿真过程中加入厂家的器件库,并对仿真器进行一些必要的配置,不然仿真器并不认识其中的底层元件,也就无法进行仿真了。
3、时序仿真 (后仿真)
在设计流程中的最后一个仿真是时序仿真。在设计布局布线完成以后可以提供一个时序仿真模型,这种模型中也包括了器件的一些信息,同时还会提供一个 SDF 时序标注文件(Standard Delay format Timing Anotation)。SDF 时序标注最初使用在 Verilog 语言的设计中,现在 VHDL 语言的设计中也引用了这个概念。对于一般的设计者来说并不需知道 SDF。
小结
行为级仿真是必须的,能够确保你所设计的功能是否正确,综合后功能仿真是有必要的,能够排除大部分的时序问题,至于后仿真,只能是解决疑难杂症时再采取的大招了,因为非常耗费时间,所以一般不建议做后仿真。
5、下载验证
5.1、添加引脚约束
在仿真验证完成后,接下来对引脚进行分配,并上板验证。本实验中,系统时钟、按键复位以及四个时钟输出端口的管脚分配。(添加约束文件.XDC,详细步骤见:Vivado 下 LED 流水灯实验_OliverH-yishuihan的博客-CSDN博客中的 “4.3、添加 XDC管脚约束文件”)
约束文件名称为“ip_clk_wiz.xdc”,具体代码内容如下:
############## clock define 时钟引脚、电平信号约束#####黑金-FPGA##################
create_clock -period 5.000 [get_ports sys_clk_p]
set_property PACKAGE_PIN R4 [get_ports sys_clk_p]
set_property IOSTANDARD DIFF_SSTL15 [get_ports sys_clk_p]
############## reset key define##########################
set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
############## 管脚 define##########################
set_property -dict {PACKAGE_PIN G21 IOSTANDARD LVCMOS33} [get_ports clk_out1]
set_property -dict {PACKAGE_PIN G22 IOSTANDARD LVCMOS33} [get_ports clk_out2]
set_property -dict {PACKAGE_PIN C22 IOSTANDARD LVCMOS33} [get_ports clk_out3]
set_property -dict {PACKAGE_PIN B22 IOSTANDARD LVCMOS33} [get_ports clk_out4]
5.2、上板验证
编译工程并生成 ip_clk_wiz.bit 文件后,此时将下载器一端连接电脑,另一端与开发板上的 JTAG 下载口连接,连接电源线,并打开开发板的电源开关。
点击 Vivado 左侧“Flow Navigator”窗口最下面的“Open Hardware Manager”-->“Open Target”-->“Auto connect”,如果此时 Vivado 软件识别到下载器,则点击“Hardware”窗口中“Progam Device”,在弹出的界面中选择“Program”下载程序。再把 bit 文件下载到 FPGA 中,接下去我们就可以用示波器来测量输出时钟波形了。
&&&
用示波器探头的地线连接到开发板上的地(AX7A035 开发板 J11 的 PIN1 脚,AX7A100/ X7204 开发板 J13 的 PIN1 脚),信号端连接 AX7A100/ AX7A200 开发板 J13 的 PIN3 脚(测量的时候需要注意,避免示波器表头碰到其它管脚而导致电源和地短路)。示波器依次为 G21 (100MHz)、G22(100MHz_180)、C22(50MHz)和 B22(25MHz)进行测试。 这时我们可以在示波器里看到 25Mhz 的时钟波形,波形的幅度为 3.3V, 占空比为 1:1,波形显示如下图所示:
6、本章总结
通过前几节的学习,我们总结一下本章所需掌握的几个知识点:
1、本章节我们主要讲解了 Vivado 软件中 PLL IP 核的调用、配置和使用方法,读者要牢记于心,这对后面章节的学习至关重要,能大大提高大家的开发效率。IP 核调用(例化)格式如下所示:
//MMCM/PLL IP核的例化
clk_wiz_0 clk_wiz_0
(
// Clock out ports
.clk_out1 (clk_out1), // output clk_out1_100m
.clk_out2 (clk_out2), // output clk_out2_100m_180
.clk_out3 (clk_out3), // output clk_out3_50m
.clk_out4 (clk_out4), // 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
.clk_in1_p (sys_clk_p), // input clk_in1_p
.clk_in1_n (sys_clk_n) // input clk_in1_n
);
7、拓展训练
在经过本章的学习后,相信大家已经掌握了 PLL 的使用方法,我们可以尝试进行以下扩展训练: 1、PLL IP 核在未来的工程项目中会频繁运用,大家可以在课后多多熟悉该 IP 核的使用,也可以将本章实验中没有勾选的选项进行勾选后看看会有什么不同的输出效果。
2、大家可以尝试着将本次实验中的任意两路输出时钟改为 33MHz 和相位偏移 180 度的 33MHz,并观察其输出结果。这里说明一点,当时钟设置为 33MHz 时在配置界面是会出现一个警告,这条警告的大致意思可以理解为设置时钟频率与实际输出的时钟频率存在一定的偏差。
3、使用 Vivado 自带的仿真器或者联合仿真的方式对之前的例程进行仿真,以此来熟悉这两种仿真方法,建议大家以熟悉联合仿真的方式为主。