小梅哥FPGA:PLL锁相环介绍与简单应用
*实验目标:学会调用QuartusⅡ软件中的时钟管理单元(PLL)核并通过仿真了解其工作特性,学会PLL的一般用法,最终通过一个实例感受PLL分频核倍频的实际效果
实验现象:在QuartusⅡ中调用PLL,将我们50MHZ的时钟clk作为输入,输出75MHZ和100MHZ的时钟c0和c1,然后通过这三个不同频率的时钟信号来控制LED的亮灭*
一 什么是PLL?
PLL即锁相环,可以通过输入一个时钟,将此时钟进行倍频/分频来达到自己想要的时钟频率进行输出
二 PLL核的调用
以下为调用PLL的过程,默认直接next的操作省略
此例中我们只生成两个时钟
三 PLL的testbench和仿真结果
`timescale 1ns/1ns
`define clk_period 20
module PLL_tb;
//端口定义
reg areset;
reg clk;
wire c0;
wire c1;
wire locked;
//例化
PLL PLL(
.areset(areset),
.inclk0(clk),
.c0(c0),
.c1(c1),
.locked(locked)
);
//initial模块
initial clk = 1;
always#(`clk_period/2) clk = ~clk;
//激励
initial begin
areset = 1'b1;
#(`clk_period*100+1);
areset = 1'b0;
#(`clk_period*200+1)
$stop;
end
endmodule
仿真结果:
四 用PLL生成的时钟信号来控制LED灯的亮灭
本文将编写LED控制模块,和顶层LED控制模块(利用3个时钟来控制三个LED)
以下为LED控制模块
/*
我们的FPGA板的晶振是50MHZ,周期是20ns,要LED灯一秒闪烁一次的话即,0.5s变化一次
即计数器24_999_999时翻转一次。
现在不管时钟频率多少,都按计数器24_999_999来翻转
*/
module LED_PLL(
clk,
Rst_n,
LED
);
input clk;
input Rst_n;
output reg LED;
reg[24:0]cnt;
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
LED<=1'b1;
else if(cnt == 25'd24_999_999)
LED <=~LED;
else
LED <=LED;
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
cnt <= 0;
else if(cnt == 25'd24_999_999)
cnt <= 0;
else
cnt <= cnt +1'b1;
endmodule
顶层模块
module LED_PLL_top(
clk,
Rst_n,
LED
);
input clk;
input Rst_n;
output[2:0]LED;
wire c0,c1;
wire locked;
PLL PLL(
.areset(~Rst_n),
.inclk0(clk),
.c0(c0),
.c1(c1),
.locked(locked)
);
LED_PLL LED0(
.clk(clk),
.Rst_n(Rst_n),
.LED(LED[0])
);
LED_PLL LED1(
.clk(c0),
.Rst_n(Rst_n),
.LED(LED[1])
);
LED_PLL LED2(
.clk(c1),
.Rst_n(Rst_n),
.LED(LED[2])
);
endmodule
五 testbench的编写
在这个testbench中,我将上面的24_999_999改成了249,不然仿真过程太长,但是在进行板机验证的时候改回为249_999_999.
`timescale 1ns/1ns
`define clk_period 20
module LED_PLL_top_tb;
//端口定义
reg clk;
reg Rst_n;
wire[2:0]LED;
//例化
LED_PLL_top LED_PLL_top(
.clk(clk),
.Rst_n(Rst_n),
.LED(LED)
);
//initial模块
initial clk = 1;
always#(`clk_period/2) clk = ~clk;
//激励
initial begin
Rst_n = 1'b0;
#(`clk_period * 20 + 1);
Rst_n = 1'b1;
#(`clk_period * 25_000_0);
$stop;
end
endmodule