目录
一:IP核简介(具体可参考野火FPGA文档)
二: 章节导读
三:PLL电路原理
3.1 PLL基本实现框图
3.2 PLL倍频实现
3.3 PLL分频实现
四: 基于 PLL 的多时钟 LED 驱动设计
4.1 配置 Clocking Wizard 核
4.2 led 闪烁控制
4.2.1 LED闪烁代码设计
4.3 顶层模块代码设计
4.4 仿真测试文件
4.5 仿真结果
4.6 管脚约束文件
4.7 上板验证结果
HDL 语言形式---(软核)硬件描述语言;可进行参数调整、复用性强;布局、布线灵活;设计周期短、设计投入少网表形式---(固核)完成了综合的功能块;可预布线特定信号或分配特定的布线资源。版图形式---(硬核)硬核是完成提供设计的最终阶段产品-掩膜(Mask);缺乏灵活性、可移植性差;更易于实现IP核的保护。IP核缺点:
- IP核往往不能跨平台使用
- IP核不透明,看不到内部核心代码
- 定制IP需额外收费
- 鉴相鉴频器 PFD(Phase Frequency Detector):对输入的基准信号(通常是来自频率稳定的晶振)和反馈回路的信号进行频率的比较,输出一个代表两者相位差异的信号。若相同则输出0 。参考时钟大于对比时钟频率会输出变大的成正比的值,小于就变小的成正比的值。
电荷泵(CP): 根据 PFD 输出的信号,产生对应电压。 环路滤波器 LF(Loop Filter): 用于控制噪声的带宽,滤掉高频噪声, 保留直流部分。 压控振荡器 VCO(Voltage Controlled Oscillator): 根据滤波器输入的电压,输出对应频率的周期信号。环路滤波器输入的电压越大 VCO 输出 的频率越高,进而产生 N 倍于输入时钟的新时钟。
下图中鉴相鉴频器 PFD(Phase Frequency Detector)是用来比较输入参考信号与反馈信号的频率与相位的。最终它们会趋近于相同,及输出为0。
从下图可以看出倍频多出了一个DIV倍频环节,如果输入信号是50MHz的频率,因为鉴相鉴频器 PFD的两端最终归趋近于相等,则经过DIV之后的频率会变成50MHz。即如果是2倍频,则pll_out会变成100MHz输出。实现倍频输出。
从下图可以看出分频多出了一个DIV分频环节放在输入信号那里,如果输入信号是50MHz的频率,如果分频器DIV是5倍分频,则输入PFD的频率是10M,因为鉴相鉴频器 PFD的两端最终归趋近于相等,则经过反馈回路输出的频率也为10MHz。则pll_out会变成10MHz输出。实现5分频输出。
module led_ctrl(
input clk,
input reset_n,
output reg led
);
parameter MCNT = 1000_0000;
reg [29:0]cnt;
//led翻转计数逻辑
always@(posedge clk or negedge reset_n)
if(!reset_n)
cnt <= 0;
else if(cnt >= MCNT-1)
cnt <= 0;
else
cnt <= cnt + 1;
always@(posedge clk or negedge reset_n)
if(!reset_n)
led <= 0;
else if(cnt >= MCNT-1)
led <= ~led;
else
led <= led;
endmodule
module pll_led(
input sys_clk,
input reset_n,
output [3:0]led
);
wire locked ;
wire clk_100m ;
wire clk_100m_s90 ;
wire clk_200m ;
wire clk_200m_d20 ;
led_ctrl #(
.MCNT (5000_0000)
)
led_ctrl_inst0(
.clk (clk_100m),
.reset_n (locked),//当locked信号为高电平时方可使用,其输出的才是稳定的时钟信号。
.led (led[0])
);
led_ctrl #(
.MCNT (5000_0000)
)
led_ctrl_inst1(
.clk (clk_100m_s90),
.reset_n (locked),
.led (led[1])
);
led_ctrl #(
.MCNT (5000_0000)
)
led_ctrl_inst2(
.clk (clk_200m),
.reset_n (locked),
.led (led[2])
);
led_ctrl #(
.MCNT (5000_0000)
)
led_ctrl_inst3(
.clk (clk_200m_d20),
.reset_n (locked),
.led (led[3])
);
clk_wiz_0 clk_wiz_0_inst
(
// Clock out ports
.clk_100m(clk_100m), // output clk_100m
.clk_100m_s90(clk_100m_s90), // output clk_100m_s90
.clk_200m(clk_200m), // output clk_200m
.clk_200m_d20(clk_200m_d20), // output clk_200m_d20
// Status and control signals
.resetn(reset_n), // input resetn
.locked(locked), // output locked
// Clock in ports
.sys_clk(sys_clk)); // input sys_clk
endmodule
`timescale 1ns / 1ps
module pll_led_tb();
reg sys_clk ;
reg reset_n ;
wire clk_100m ;
wire clk_100m_s90 ;
wire clk_200m ;
wire clk_200m_d20 ;
wire [3:0]led ;
pll_led pll_led(
.sys_clk (sys_clk) ,
.reset_n (reset_n) ,
.clk_100m (clk_100m) ,
.clk_100m_s90(clk_100m_s90) ,
.clk_200m (clk_200m) ,
.clk_200m_d20(clk_200m_d20) ,
.led (led)
);
//重定义,缩短仿真时间
defparam pll_led.led_ctrl_inst0.MCNT = 26'd500;
defparam pll_led.led_ctrl_inst1.MCNT = 26'd500;
defparam pll_led.led_ctrl_inst2.MCNT = 26'd500;
defparam pll_led.led_ctrl_inst3.MCNT = 26'd500;
initial sys_clk = 1'b1;
always #10 sys_clk = ~sys_clk;
initial
begin
reset_n = 0;
#201;
reset_n = 1;
#20000;
$stop;
end
endmodule
set_property IOSTANDARD LVCMOS33 [get_ports reset_n]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property PACKAGE_PIN U18 [get_ports sys_clk]
set_property PACKAGE_PIN F20 [get_ports reset_n]
set_property PACKAGE_PIN G17 [get_ports {led[0]}]
set_property PACKAGE_PIN G19 [get_ports {led[1]}]
set_property PACKAGE_PIN G18 [get_ports {led[3]}]
set_property PACKAGE_PIN G20 [get_ports {led[2]}]
至此PLL的IP核调用实验完美成功。