在FPGA系统设计中,几乎所有地方都可以用到PLL,也有些地方是非用到PLL不可。
在某些对系统时钟频率没有固定要求的系统中,外部晶振输入的时钟可以直接作为逻辑驱动时钟,也可以通过PLL将该时钟进行降频,以得到较低的工作时钟,在不影响系统功能实现的前提下降低系统功耗。
另外一些应用,则必须在指定频率的时钟信号下才能正常工作,常见于通信协议类应用,如以太网、USB、PCIE等等,在这些应用中,必须使用指定频率的时钟信号,如果没有刚好满足条件的外部时钟源,则必须通过片内PLL生成相应的时钟信号来进行驱动。在某些实时性要求较高的应用中,如数字信号处理,图像处理等等,提高系统工作时钟能够提升系统的性能,这一类应用中,也往往使用PLL进行倍频和分频,以得到较高频率的时钟,用以提升系统整体性能。
再有一个常见的应用就是生成两路频率相同,相位不同的时钟供SDRAM控制器和SDRAM芯片使用。根据SDRAM芯片的工作原理,SDRAM控制器的工作时钟和SDRAM芯片的工作时钟需要保持180°的相位差才能保证正确的读写数据。所以这里就可以使用PLL的相位控制功能来产生两路相位不同的时钟,以分别供控制器和SDRAM芯片使用。
下面我们看一下实用PLL设置不同频率控制led闪烁例程:
//Top.vmodulePLL_LED(Clk,Rst_n,LED);inputClk;inputRst_n;output[3:0]LED;wirec0;//25Mwirec1;//75Mwirec2;//100Mwirelocked;pllpll(.areset(~Rst_n),.inclk0(Clk),.c0(c0),.c1(c1),.c2(c2),.locked(locked));counter#(.CNT_MAX(25'd24_999_999)///////////////////)counter0(.Clk(c0),.Rst_n(Rst_n),.led(LED[0]));counter#(.CNT_MAX(25'd24_999_999)///////////////////)counter1(.Clk(c1),.Rst_n(Rst_n),.led(LED[1]));counter#(.CNT_MAX(25'd24_999_999)///////////////////)counter2(.Clk(c2),.Rst_n(Rst_n),.led(LED[2]));counter#(.CNT_MAX(25'd24_999_999)///////////////////)counter3(.Clk(Clk),.Rst_n(Rst_n),.led(LED[3]));endmodulemodulecounter(Clk,Rst_n,led);inputClk;//系统时钟inputRst_n;//全局复位,低电平复位outputregled;//led输出reg[24:0]cnt;//定义计数器寄存器parameterCNT_MAX=25'd24_999_999;//计数器计数进程always@(posedgeClkornegedgeRst_n)if(Rst_n==1'b0)cnt<=25'd0;elseif(cnt==CNT_MAX)cnt<=25'd0;elsecnt<=cnt+1'b1;//led输出控制进程always@(posedgeClkornegedgeRst_n)if(Rst_n==1'b0)led<=1'b1;elseif(cnt==CNT_MAX)led<=~led;elseled<=led;endmodule//`tb`timescale1ns/1ps`defineclk_period20modulePLL_LED_tb;regClk;regRst_n;wire[3:0]LED;PLL_LEDPLL_LED(.Clk(Clk),.Rst_n(Rst_n),.LED(LED));///////////////////defparamPLL_LED.counter0.CNT_MAX=24;defparamPLL_LED.counter1.CNT_MAX=24;defparamPLL_LED.counter2.CNT_MAX=24;defparamPLL_LED.counter3.CNT_MAX=24;initialClk=1;always#(`clk_period/2)Clk=~Clk;initialbeginRst_n=1'b0;#(`clk_period*20+1);Rst_n=1'b1;#(`clk_period*2000);$stop;endendmodule
仿真波形图: