赞
踩
FPGA中时钟管理模块(CMT)包括PLL和MMCM,用于将时钟倍频(比如输入时钟25M,我们要产生50M时钟)、分频(在不影响系统功能的前提下,较低的工作时钟,能够降低系统功耗)、改变相位偏移或占空比等。
当需要上板时,由于板上晶振时钟固定,所以其他频率的时钟产生就要用到PLL或者MMCM。两者类似,MMCM可以完成PLL的所有功能外加一些高级功能。
其中具体的一些时钟域,BUFG等时钟资源介绍,以及FPGA中的PLL和MMCM介绍可参考时钟IP核(MMCM PLL)、RAM 和 FIFO 实验-哔哩哔哩(待学)
这里只介绍PLL锁相环。
如果只是调用ip的话,知道怎样使用即可
vivado中的调用及上板测试可以参考:
FPGA实战(五)时钟IP核(MMCM PLL)
基本就是调用ip,然后设置一个输入时钟一个输出时钟;注意其中有一个locked信号,当locked信号拉高的时候代表锁相环输出信号已经稳定。
locked信号常被用于复位信号。
另外,时钟管理IP核并不能产生任意频率的时钟信号。 产生的时钟信号与输入之间仅能是M/N的关系,其中M、N必须是整数(在原理部分会介绍)。
PLL组成:
锁相环是一种以消除频率误差为目的的反馈控制电路。原理是利用相位误差消除频率误差,所以当电路平衡时,会有剩余相位误差,但频率误差为0。
具体推导:
也可以参考一文弄懂锁相环(PLL)的工作原理及应用
终止最终达到的效果就是输入输出有相位差(VCO需要一定的电压驱动它到正确的频率,所以一定有相差)但是频率相等,就如下图所示。
那对于分频是怎样实现的呢?
如下图,插入分频模块即可,这样就可以实现输出/输出=N/M, N M为整数。
图片来自锁相环的工作原理
我只使用锁相环对板子就行了简单的分频,基于PYNQ-Z2板子,从125M到50M,写了一个灯亮灭的程序,等locked信号稳定后才计数。
程序如下:
module led( (* MARK_DEBUG="true" *)input sys_clk, input clk_restn, output reg[3:0] led ); reg[31:0] timer_cnt; (* MARK_DEBUG="true" *)wire clk; (* MARK_DEBUG="true" *)wire locked_out; /* initial begin led<=0; timer_cnt<=0; end */ clk_wiz_0 clk_wiz ( // Clock out ports .clk_out1(clk), // output clk_out1 // Status and control signals .reset(clk_restn), // input resetn // Clock in ports .clk_in1(sys_clk), // input clk_in1 .locked(locked_out)); // output locked always@(posedge clk) begin if((locked_out==1) && (timer_cnt>=32'd49999999))begin //if(timer_cnt>=32'd4999)begin led<=~led; timer_cnt<=0; end else if(locked_out==1)begin led<=led; timer_cnt<=timer_cnt+1; end else begin led<=led; timer_cnt<=0; end end endmodule
我设置的是1s亮1s灭,但是实际上板出现的问题是1s亮2s灭或者2s灭1s亮,肉眼可见的有问题。
上板抓信号发现locked信号拉高之后还会拉低,不是一直拉高,这就导致拉低时计数清零,拉高又重新计数,时长就变长了。
最后发现问题是板子有问题,换了板子就正确了。应该是原来板子晶振有问题,会周期性不稳定,导致PLL的locked信号周期性拉低拉高。
上述程序也有一些问题,这里记录一下:
1、initial块不要写在要综合的代码中,因为它不可综合,用复位来设置初值
2、clk是分频出来的,最好后面模块也给复位,不然如果PLL出错后面clk控制的就都没办法控制了
3、locked_out==1这样写是没问题的,如果板子时钟没问题就是拉高之后不会拉低了。也确实要等始终稳定locked_out=1再进行操作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。