实验现象:
调用IP核,配置工作方式,输入为50M,利用PLL生成25M,75M,100M三中时钟,用仿真观察时序,检查PLL对分频、倍频处理的正确性。
PLL介绍:
PLL——phase locked loop相位锁定环路
功能1:
对时钟信号进行分频倍频,得到不同频率的时钟信号。例如,在各种通信协议中,USB、PCIE、以太网这类协议,都有各自固定的数据传输频率。USB2.0协议芯片CY7C68013使用片外24M晶振,倍频20倍到480M以供传输数据使用;以太网协议芯片W5500使用片外25M晶振,倍频6倍到150M以供传输数据使用。
功能2:
对同一个PLL生成的多个时钟进行相位控制,以得到期望的时间差。例如,一个时钟通过PLL产生频率相同,相位不同的两路时钟供SDRAM控制器和SDRAM芯片使用。SDRAM控制器和SDRAM芯片要求时钟要严格保证180°相位差
,但clk2从fpga到SDRAM芯片往往会有延迟
,所以就需要PLL控制两路频率相同信号的相位差。
配置PLL IP核:
testbench测试文件(这个测试不需要rtl程序):
`timescale 1ns/1ns
`define clock_period 20
module PLL_tb;
/***************定义输入输出*************/
reg areset;
reg clk;
wire c0;
wire c1;
wire c2;
wire locked;
/***************例化PLL模块*************/
PLL PLL(
.areset(areset),
.inclk0(clk),
.c0(c0),
.c1(c1),
.c2(c2),
.locked(locked)
);
/*************产生系统时钟激励***********/
initial clk=1;
always #(`clock_period/2)clk=~clk;
/***************先置位areset观察输出,再areset置0,观察输出和相位锁定时间*************/
initial begin
areset=1;
#(`clock_period*20+1);
areset=0;
#(`clock_period*20);
end
endmodule
波形图:
在areset置位(为高)时,相位不能锁定(locked不能置高,PLL不能工作)。
当areset变成0时,PLL不会立刻相位锁定,需要经过一段不稳定时间,然后相位锁定并稳定输出期望的分频倍频时钟。
实验二:
用PLL分频倍频产生25M、50M、100M时钟,控制LED,观察闪烁规律。
rtl程序(TOP文件):
module PLL_LED(clk50M,rst_n,led);
input clk50M;
input rst_n;
output [3:0] led;
wire c0;
wire c1;
wire c2;
wire locked;
PLL PLL(
.areset(~rst_n),
.inclk0(clk50M),
.c0(c0),
.c1(c1),
.c2(c2),
.locked(locked)
);
ledcounter #(.MAX_CNT(25'd10000))
u0(
.clk(clk50M),
.rst_n(locked),
.ledout(led[0])
);
ledcounter #(.MAX_CNT(25'd10000))
u1(
.clk(c0),
.rst_n(locked),
.ledout(led[1])
);
ledcounter #(.MAX_CNT(25'd10000))
u2(
.clk(c1),
.rst_n(locked),
.ledout(led[2])
);
ledcounter #(.MAX_CNT(25'd10000))
u3(
.clk(c2),
.rst_n(locked),
.ledout(led[3])
);
endmodule
子模块:
module ledcounter(clk,rst_n,ledout);
input clk;
input rst_n;
output reg ledout;
reg [24:0] counter;
parameter MAX_CNT=25'd24_999_999;
/**********************计数器产生********************/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
counter<=25'd0;
else if(counter==MAX_CNT)
counter<=25'd0;
else
counter<=counter+1'b1;
end
/***********到达设定时刻MAX_CNT就会翻转LED************/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
ledout<=1'b0;
else if(counter==MAX_CNT)
ledout<=~ledout;
else
ledout<=ledout;
end
endmodule
testbench文件:
`timescale 1ns/1ns
`define clock_period 20
module PLL_LED_tb;
reg clk;
reg rst_n;
wire [3:0]led;
PLL_LED PLL_LED(
.clk50M(clk),
.rst_n(rst_n),
.led(led)
);
defparam PLL_LED.u0.MAX_CNT=24;
defparam PLL_LED.u1.MAX_CNT=24;
defparam PLL_LED.u2.MAX_CNT=24;
defparam PLL_LED.u3.MAX_CNT=24;
initial clk=1;
always #(`clock_period/2) clk=~clk;
initial begin
rst_n=0;
#(`clock_period*20+1);
rst_n=1;
#(`clock_period*200);
$stop;
end
endmodule
波形图:
可以看到LED0~3分别代表50M、25M、75M、100M时钟计24个数翻转一次LED的波形图。可以看出倍数关系。