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

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

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

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

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

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

       下一篇:FPGA例程(6):UART串口通讯协议解析-ZEEKLOG博客


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创建例程-ZEEKLOG博客

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

点击IP Catalog-->选择Clocking Wizard

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

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

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

我们点击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创建例程-ZEEKLOG博客

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

## ----------- 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,尤其是一些因为不当的设计被优化掉的信号,从综合后仿真和实现后仿真能明显的看出来。

Read more

【OpenClaw从入门到精通】第04篇:Web/TUI/钉钉全打通!OpenClaw多端交互实测指南(2026避坑版)

【OpenClaw从入门到精通】第04篇:Web/TUI/钉钉全打通!OpenClaw多端交互实测指南(2026避坑版)

摘要:本文聚焦OpenClaw三大核心交互方式,针对新手“不知如何与AI助理沟通”的痛点,提供Web控制台、TUI终端、聊天软件(以钉钉为核心)的完整实操流程。Web控制台适配电脑端深度配置,TUI终端适合服务器远程维护,聊天软件满足手机端移动办公,三者协同实现“随时随地召唤AI”。文中包含2026实测的命令代码、配置步骤、问题排查方案,所有案例为虚拟构建,代码未上传GitHub,兼顾新手入门与进阶实操,帮助读者快速打通多端交互,最大化OpenClaw使用效率。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:高并发+性能调优终极实战】【Coze搞钱实战:零代码打造吸金AI助手】

MC.JS WEBMC 1.8.8 PLUS MOBILE在在线教育中的应用案例

快速体验 1. 打开 InsCode(快马)平台 https://www.inscode.net 2. 输入框内输入如下内容: 创建一个基于MC.JS WEBMC 1.8.8 PLUS MOBILE的教育演示项目。要求:1) 实现一个简单的3D编程教学环境;2) 包含5个循序渐进的编程练习任务;3) 添加教学注释和提示系统;4) 支持移动设备访问;5) 提供学生作品展示区。请使用响应式设计,确保在不同设备上都有良好的用户体验。 1. 点击'项目生成'按钮,等待项目生成完整后预览效果 最近在尝试将游戏开发引入编程教学时,发现MC.JS WEBMC 1.8.8 PLUS MOBILE这个工具特别适合做在线教育场景的实践。通过浏览器就能创建3D编程环境的特点,

【年终总结】从非科班无实习到准字节前端:我始终相信,开发之外的事,才是破局关键

【年终总结】从非科班无实习到准字节前端:我始终相信,开发之外的事,才是破局关键

目录 【年终总结】从非科班无实习到准字节前端:我始终相信,开发之外的事,才是破局关键 一、求其外,善其内 1、坚持出发点正确的博文写作 2、博文更新对我心态的淬炼 3、社区交流对我视野的启发 4、向外拓展,反哺内修 二、陷入前端则前端死,跳出前端则前端活 1、从不务正业到泛前端 2、从泛前端到大前端,从有形到无形 三、秋招多少事 四、结语         作者:watermelo37         ZEEKLOG优质创作者、华为云云享专家、阿里云专家博主、腾讯云“创作之星”特邀作者、火山KOL、支付宝合作作者,全平台博客昵称watermelo37。         一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。 --------------------------------------------------------------------- 温柔地对待温柔的人,包容的三观就是最大的温柔。

Rust与WebAssembly深度实战——将高性能Rust代码运行在浏览器与Node.js

Rust与WebAssembly深度实战——将高性能Rust代码运行在浏览器与Node.js

Rust与WebAssembly深度实战——将高性能Rust代码运行在浏览器与Node.js 一、学习目标与重点 1.1 学习目标 1. 理解WebAssembly基础:深入掌握WebAssembly(Wasm/Wasmtime)的核心定义、运行机制、与JavaScript的性能对比 2. 掌握Rust到Wasm的编译:熟练使用wasm-pack、cargo-web等工具链,完成Rust代码到Wasm模块的编译、打包、优化 3. 精通Rust与JavaScript交互:实现双向交互(Rust调用JS函数、JS调用Rust函数),处理复杂数据类型(数组、对象、字符串),管理内存(Wasm线性内存的分配与释放) 4. 开发真实Wasm应用:编写浏览器端高性能任务(Canvas图像滤镜、WebGL计算辅助)、Node.js端计算密集型任务(图像处理、加密解密、数据压缩) 5. 优化Wasm模块:使用wasm-opt工具优化Wasm体积,学习代码分割、懒加载、模块缓存