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

Flutter 组件 http_retry 的适配 鸿蒙Harmony 深度进阶 - 驾驭分布式负载感知重试、实现鸿蒙端高可靠通讯与协议幂等性审计方案

Flutter 组件 http_retry 的适配 鸿蒙Harmony 深度进阶 - 驾驭分布式负载感知重试、实现鸿蒙端高可靠通讯与协议幂等性审计方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 http_retry 的适配 鸿蒙Harmony 深度进阶 - 驾驭分布式负载感知重试、实现鸿蒙端高可靠通讯与协议幂等性审计方案 前言 在前文中,我们探讨了 http_retry 在鸿蒙(OpenHarmony)生态中解决单一移动终端弱网重试的基础实战。但在真正的“分布式工业物联网集成”、“跨设备协同办公资产同步”以及“需要对接具备动态压力管控的超大规模云原生后端”场景中。简单的指数退避往往难以应对复杂的网络分位震荡。面对一个需要在鸿蒙手机、智能穿戴设备与边缘网关之间,根据当前全网的平均负载压力(Load Pressure)动态调节重试节奏,并且要求在执行涉及核心资产变更(如:支付订单、库存锁定)的重试时执行绝对严密的协议幂等性(Idempotency)校验的高阶需求。如果缺乏一套具备分布式感知的重试调度模型。不仅会导致后端服务在故障恢复瞬间遭遇“重试波峰”引发再次崩溃,更会因为对非幂等操作的盲目重试。引发严重的业务资产错乱。 我们需要

By Ne0inhk
Flutter 组件 shelf_router 的适配 鸿蒙Harmony 实战 - 驾驭官方标准路由器架构、实现鸿蒙端 HTTP 流量精密分发与逻辑路由审计方案

Flutter 组件 shelf_router 的适配 鸿蒙Harmony 实战 - 驾驭官方标准路由器架构、实现鸿蒙端 HTTP 流量精密分发与逻辑路由审计方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 shelf_router 的适配 鸿蒙Harmony 实战 - 驾驭官方标准路由器架构、实现鸿蒙端 HTTP 流量精密分发与逻辑路由审计方案 前言 在鸿蒙(OpenHarmony)生态的分布式业务中继、政务级内嵌 API 管理平台以及需要承载大规模高频交互请求的各类全栈式应用开发中,“路由的精确支配与逻辑安全性”是决定系统架构稳健性的命门所在。面对包含上百个 RESTful 端点的复杂服务模型、需要动态解析包含 UUID、日期等多种格式的 URL 参数,或者是需要针对鸿蒙手机与智慧大屏执行差异化的路由匹配。如果仅仅依靠原始的字符串拆分或低性能的手写拦截逻辑。不仅会导致路由解析执行效率的低下,更会因为缺乏一套工业级的“官方契约”规范。引发鸿蒙端微服务接口在面对异常报文时的逻辑脆弱性风险。 我们需要一种“官方背书、匹配闭环”的路由艺术。 shelf_router 是一套由 Dart 官方团队维护的、

By Ne0inhk
SkyWalking - Spring Cloud Alibaba 全链路追踪实战

SkyWalking - Spring Cloud Alibaba 全链路追踪实战

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕SkyWalking这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * SkyWalking - Spring Cloud Alibaba 全链路追踪实战 🚀 * 1. 环境准备与核心概念 🧰 * 1.1 核心概念解析 * 1.2 环境准备 * 2. 构建 Spring Cloud Alibaba 微服务项目 🏗️ * 2.1 创建父工程 * 2.2 构建 `inventory-service`(库存服务) * 2.3 构建 `order-service`(订单服务) * 2.4 验证基础功能 * 3. 集成

By Ne0inhk