本文转载自CSDN博主「孤独的单刀」的原创文章,原文链接:https://blog.csdn.net/wuzhikaidetb/article/details/125976192
1、PLL IP的定制
由于MMCM算是PLL一个功能上的超集,多出的动态相位移动和展频功能我们本章不详细讲解,所以以下内容均使用PLL IP核实现。
(1)在新建一个工程后, 点击IP Catalog
(2)点击后会出现 IP Catalog 页面,在 IP 核的搜索框中搜索 clocking
(3)根据筛选,双击选择PLL核 Clocking Wizard
Page 1 Cloking Options
① 时钟监控(Enable Clock Monitoring ):实时监测,可以随时检测时钟
② 实现类型(primitive):可选择PLL还是MMCM来实现,一般来讲PLL足够实现大部分功能,MMCM适合更高级一些的应用,如动态移相或者展频等
③ 时钟特性
◇ Frequency Synthesis:频率综合,勾选上以后才能修改输出想要的时钟频率
◇ Phase Alignment:相位对齐,勾选上后输入信号与输出信号相位是一致的,代价是多用了一个BUFG
◇ Dynamic Reconfig : 可以通过AXI4接口在使用过程中动态修改IP配置,实现更灵活的时钟输出,具体实现可以参考:xapp888_7Series_DynamicRecon
◇ Safe Clock Starup : 在时钟没稳定之前不输出,好处是时钟更加稳定安全,坏处可能影响性能
◇ Minimize Power : 优化功耗,代价是性能可能受影响
④ 时钟抖动(Jitter)优化
◇ Balanced:默认选项,性能、功耗平衡状态
◇ Minimize Output Jitter:最小化输出时钟抖动,代价是功耗变大和可能会导致相位误差
◇ Maximize Input Jitter filtering:最大化输入时钟过滤,允许输入时钟信号的抖动变大(即允许更差质量的输入时钟信号),但是可能会导致输出时钟信号的抖动变大
⑤ 动态重配置选项:没有勾选该功能,所以不说了
⑥ 输入时钟信息
◇ 可选输入两个时钟信号作为输入
◇ 配置输入时钟的频率、抖动、来源
Page 2 Output Clocks
① 输出时钟信息设置:勾选需要输出的时钟信息,包括频率,相位关系和占空比等,需要注意的是设定值不一定能实现,一切以实际值为准。我们选定5个不同类型的时钟频率,具体信息见表格。
② 输出时钟顺序:勾选不同信号的输出顺序,需要在Page1勾选Safe Clock Starup选项才能使用
③ 时钟反馈:只有在Page1勾选了Phase Alignment选项才可以勾选
◇ automatic control on-chip与user-controlled on-chip:如果你的输出时钟信号是在FPGA内部使用的,那么反馈路径就是on chip的,自动和用户自定的区别是反馈时钟引脚是自动连接还是开放给用户自己连接
◇ automatic control off-chip与user-controlled off-chip:如果你的输出时钟信号是给FPGA外部使用的,那么反馈路径就是off chip的,自动和用户自定的区别是反馈时钟引脚是自动连接还是开放给用户自己连接。automatic control off-chip模式下还需要指定反馈引脚是单端信号(single ended)还是差分信号(differential)
④ 可选项
◇ reset:复位信号
◇ power_down:掉电模式(关闭PLL,停止输出)
◇ locked:置位时表示PLL输出信号有效,平常使用PLL一定要等该信号有效后才使用输出时钟信号
⑤ 复位类型:选择高电平复位还是低电平复位。建议选择xilinx常用的高电平复位。
Page 3 Port Renaming
输出端口的信号重命名,一般为了通用性,不建议改名。
Page 4 MMCM Settings
直接对PLL底层原语进行操作,实现更详细化的定制设计。一般不使用。
Page 5 Summary
PLL IP核设计信息汇总,确认一下设计信息。
2、PLL IP的例化与测试
2.1、例化一个PLL IP核
按上述步骤生成IP后,复制 IP核自带的例化模板。
2.2、编写Testbench文件
我们直接编写testbench来例化PLL IP核进行测试
`timescale 1ns / 1ns
module tb_pll_test();
reg clk_in; // 输入时钟50M
reg reset; // 高有效的复位信号
wire locked;
wire clk50_90d; // 50M,偏移90度
wire clk50_n90d; // 50M,偏移-90度
wire clk50_d75; // 50M,占空比75%
wire clk_100; // 100M
wire clk_150; // 150M
always #10 clk_in = ~clk_in; //产生输入时钟
// 初始化输入信号
initial begin
reset = 1'b1;
clk_in = 1'b0;
#100
reset = 1'b0;
wait(locked); // PLL输出有效
#1000 $finish;
end
// 例化PLL IP核
clk_wiz_0 instance_name
(
// Clock out ports
.clk50_90d(clk50_90d), // output clk50_90d
.clk50_n90d(clk50_n90d), // output clk50_n90d
.clk50_d75(clk50_d75), // output clk50_d75
.clk100(clk_100), // output clk100
.clk150(clk_150), // output clk150
// Status and control signals
.reset(reset), // input reset
.locked(locked), // output locked
// Clock in ports
.clk_in1(clk_in) // input clk_in1
);
endmodule
2.3、仿真测试
使用vivado自带的仿真工具simulator运行仿真,仿真结果如下:
接下来分别看下各个信号:
(1)clk50_90d:50M,偏移90度
(2)clk50_n90d:50M,偏移-90度
(3)clk50_d75:50M,占空比75%
(4)clk_100:100M
(5)clk_150:150M
可以看到,所有的输出时钟信号均与预期设计一致,仿真成功。
3、总结与参考
就一般应用而言,PLL IP核上手非常简单;至于动态重配置和动态相位移动功能来说,可能稍微麻烦一点
平常的设计中不要使用分频时钟,而应该尽量使用PLL or MMCM来实现时钟信号的设计
参考资料1:pg065-clk-wiz