FPGA例程(5):时钟(clock)分频倍频(PLL/MMCM)实验--vivado行为级仿真、综合后仿真和实现后仿真说明

《FPGA经典例程及解读--基于xilinx K325T平台》系列导航

本专栏主要针对与想学习FPGA的同学,从基础的点灯到之后的复杂功能实战例程,从入门到进阶,通过这些例程的学习和了解,希望可以帮助你从一个FPGA小白进阶到FPGA中级阶段,能够处理工作中大多数的FPGA使用场景。

本篇是该系列的第五篇内容

上一篇:FPGA例程(4):按键消抖实验-CSDN博客

**下一篇:**关注我,第一时间获取更新!!


1 引言

很多初学者会遇到一个问题,我们硬件的输入时钟只有100MHz,但是我们内部需要使用200MHz或者50MHz这样的时钟,我们该怎么办呢?其实在FPGA内部集成了PLL或者MMCM,不同的厂商叫法可能不同,但是功能类似,通过PLL(MMCM)可以分频和倍频,产生很多其它的时钟,本实现通过调用xilinx的clock wizard的IP核来学习PLL(MMCM)的使用方法。

2 硬件环境

开发环境使用vivado2019.1

开发板使用米联客的MK7160FA

3 实验原理

PLL,即锁相环,是FPGA中的重要资源。由于一个复杂的FPGA系统往往需要多个不同频率、相位的时钟信号,所以,一个FPGA芯片中PLL的数量是衡量FPGA芯片能力的重要指标。

7系列的FPGA使用了专用的全局(Global)和区域(Regional)IO和时钟资源来管理设计中各种的时钟需求。Clock Management Tiles(CMT)提供了时钟合成(clock frequency synthesis)、倾斜矫正(deskew)、过滤抖动(jitter filtering)功能。

每个CMTs包含一个MMCM(mixed-mode clock manager)和一个PLL。如下同所示,CMT的输入可以是BUFR、IBUFG、BUFG、GT、BUFH、本地布线(不推荐使用),输出需要接到BUFG或者BUFH后再使用

3.1 混合模式时钟管理器(MMCM)

MMCM用于在与给定输入时钟有设定的相位和频率关系的情况下,生成不同的时钟信号。MMCM提供了广泛而强大的时钟管理功能,MMCM内部的功能框图如下图所示:

3.2 数字锁相环PLL

锁相环主要用于频率综合。使用一个PLL可以从一个输入时钟信号生成多个时钟信号。PLL内部的功能框图如下图所示:

4 建立工程

按照FPGA例程(1):LED流水灯实验--vivado工程创建、编译及下载bit_vivado创建例程-CSDN博客

中的步骤,创建一个名为PLL_test的工程。

点击IP Catalog-->选择Clocking Wizard

clocking Wizard的具体说明详见:FPGA基础知识(十五):Xilinx Clocking Wizard IP核完全指南--从基础到高级应用-CSDN博客

我们的输入时钟为100MHz,我们内部需要使用200MHz和50MHz的时钟

其它参数的配置详见:FPGA基础知识(十五):Xilinx Clocking Wizard IP核完全指南--从基础到高级应用-CSDN博客

我们点击OK-->Generate生成IP核

生成的IP核如下,展开可以看到IP核的TOP层,之后我们在工程中就例化的是这个TOP层。

我们新建一个PLL_test.v文件,例化module clk_wiz_0

大家注意到,程序的最后有一段产生clk_div的程序,即将100MHz进行2分频产生50MHz,故clk_div的频率与clk_50M是一样的,只是生成的方式不同,方便大家看一下这两种方式的区别。

复制代码
module PLL_test(
input sys_clk,  //100MHz
output clk_200M,
output clk_50M,
output clk_div
);

parameter RST_DELAY = 8'd128;
reg [7:0] rst_cnt;
always @(posedge sys_clk) begin
    if(rst_cnt < RST_DELAY)begin 
        rst_cnt <= rst_cnt + 1'd1;
    end else if(rst_cnt == RST_DELAY) begin 
        rst_cnt <= rst_cnt; 
    end else begin 
        rst_cnt <=0;
    end
end
reg rst_n;
always @(posedge sys_clk) begin
    if(rst_cnt == RST_DELAY) begin 
        rst_n <= 1;
    end else begin 
        rst_n <= 0;
    end
end
//----------------------------------------------------
wire sys_rstn;
//wire clk_200M;
//wire clk_50M;
clk_wiz_0 clk_wiz_0(
.clk_200M(clk_200M),
.clk_50M(clk_50M),
.resetn(rst_n),
.locked(sys_rstn),
.clk_in1(sys_clk)
);
//-----------------------------------------------------
reg clk_div_c;
//wire clk_div;
always @(posedge sys_clk or negedge rst_n ) begin
if (!rst_n) begin
    clk_div_c <= 1'b0;
end
else begin
    clk_div_c <= ~clk_div_c;
end
end
BUFG BUFG_inst (
.O(clk_div), // 1-bit output: Clock output
.I(clk_div_c)  // 1-bit input: Clock input
);
endmodule

按照FPGA例程(1):LED流水灯实验--vivado工程创建、编译及下载bit_vivado创建例程-CSDN博客

中的步骤,添加我们的约束文件,如下:

复制代码
## ----------- clock -----------------------
create_clock -period 10.000 -name sys_clk [get_ports sys_clk]
set_property PACKAGE_PIN AA3 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS15 [get_ports sys_clk]
## ------------ led pin -----------------------------
set_property PACKAGE_PIN G14 [get_ports {clk_200M}]
set_property PACKAGE_PIN H14 [get_ports {clk_50M}]
set_property PACKAGE_PIN J10 [get_ports {clk_div}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_200M}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_50M}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_div}]

## ========================== SPI X4 =================================
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE Yes [current_design]

5 程序仿真

我们点击Add Sources-->选择Add or create simulation sources添加以下仿真激励文件。

如果我们有现成的文件,选择Add Files,选择文件路径即可

这里我们没有现成的,就点击Create File--->输入仿真激励文件名称--->OK---->Finish

就会在Simulation Sources下面产生以下tb_PLL_test.v的文件,我们开始编写测试激励:

输入时钟是100MHz,对应周期为10ns,故5ns我们执行一次反转

复制代码
module tb_PLL_test();
reg sys_clk;
initial begin
    sys_clk = 0;
end
always begin
    #5 sys_clk = ~sys_clk;
end

wire clk_200M,clk_50M,clk_div;
PLL_test DUT(
.sys_clk(sys_clk),  //100MHz
.clk_200M(clk_200M),
.clk_50M(clk_50M),
.clk_div(clk_div)
);
endmodule

5.1 行为级仿真

点击Run Simulation ,选择Run Behavioral Simulation

选择例化的名称,可以在Objects中看到相关的信号,右键选择Add to Wave Window,就可以将信号加入观测窗口的

添加好之后,设定仿真的时间,比如10us,点击Run for 10us(三角形+T的图标)就可以进行仿真了,跑完10us会自动停下

如果不知道设置多长时间可以直接点击Run All(三角形图标),等跑一下自己手动暂停即可。

仿真结果如下:

输出的clk_200m对应的周期为5ns,即200mhz时钟周期

输出的clk_50m对应的周期为20ns,即50mhz时钟周期

输出的clk_div对应的周期亦为20ns,即50mhz时钟周期

这些时钟均与sys_clk上升沿对齐

5.2 综合时序仿真

执行完Run Synthesis之后,点击Run Simulation ,选择Run Post-Synthesis Timing Simulation

通过仿真我们可以看到综合后仿真加入了延迟,会更加接近实际中芯片的运行场景

首先输入的sys_clk与输出clk_200M和clk_50M之间存在相位偏移

clk_200m与clk_50m之间也存在相位偏移,但是偏移非常小

输入的sys_clk与输出的clk_div存在相位偏移,且相位偏移要大于其与clk_50M之间的偏移

5.3 布局布线后时序仿真

完成Run Implementation之后,点击Run Simulation ,选择Run Post-Implementation Timing Simulation

通过仿真可以看出,通过布局布线之后加入了延迟,比综合后的仿真更接近于真实的情况,时序之间的相位延迟也更大一些。

6 总结

一般来说,程序的功能是否正常,我们可以先查看行为级仿真,当程序出现一些未预料的bug时,综合后仿真和实现后仿真能很好的帮助我们定位bug,尤其是一些因为不当的设计被优化掉的信号,从综合后仿真和实现后仿真能明显的看出来。

相关推荐
3有青年2 小时前
HPS cold reset pin和AVST configuration的功能和作用
fpga开发
3有青年18 小时前
Altera FPGA操作系统支持的情况分析
fpga开发
国科安芯19 小时前
卫星通讯导航FPGA供电单元DCDC芯片ASP4644S2B可靠性分析
单片机·嵌入式硬件·fpga开发·架构·安全性测试
stars-he1 天前
FPGA学习笔记-图书馆存包柜,乒乓球游戏电路设计
笔记·学习·fpga开发
从此不归路1 天前
FPGA 结构与 CAD 设计(第3章)下
ide·fpga开发
YprgDay1 天前
Vivado单独综合某一模块查看资源消耗
fpga开发·vivado
Joshua-a1 天前
高云FPGA在线调试/逻辑分析仪简要使用流程
嵌入式硬件·fpga开发·高云
博览鸿蒙2 天前
FPGA 工程中常见的基础硬件问题
fpga开发
GateWorld2 天前
FPGA 实现无毛刺时钟切换
fpga开发·实战·无毛刺时钟