前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Vivado那些事儿】动态时钟的使用

【Vivado那些事儿】动态时钟的使用

作者头像
碎碎思
发布2023-08-30 10:23:08
4610
发布2023-08-30 10:23:08
举报
文章被收录于专栏:OpenFPGA

时钟是每个 FPGA 设计的核心。如果我们正确地设计时钟架构、没有 CDC 问题并正确进行约束设计,就可以减少与工具斗争的时间。

但对于某些应用,我们希望能够更改某些IP中的时钟频率。其中一个例子是在图像处理管道中,输出分辨率可以动态变化,从而需要改变像素时钟。

众所周知,我们可以在 Zynq SoC 和 Zynq MPSoC 中使用结构时钟并在运行时更改结构时钟的频率。但是,如果我们在 Zynq 或 ZYNQ MPSoC 中使用 FPGA 或 PL,我们仍然可以使用动态配置的时钟向导在运行时更改频率。

动态配置时钟允许我们使用 AXI 接口在运行时更改时钟频率。

为了创建一个简单的示例,我们将实例化PS并将动态配置时钟IP连接到主 AXI 接口。我们将输出时钟连接到 IO 引脚,以便我们可以对其进行观察并查看频率的变化。

上面的时钟是我们打算使用的最大频率,这样可以确保时序约束和时序性能正确。下图是我们这次demo的最终设计。

接下来我们将在 Vitis 中开发软件,并且将在设计中的 IP 下看到相关驱动及文档。

开发这个IP的驱动和其他 AXI Lite 接口一样,需要对IP寄存器空间进行写入和读取。

要更改时钟频率输出,我们有两种选择。如果只生成一个时钟,我们可以使用名为 SetRate 的函数。该函数将通过AXI Lite总线传递到IP中,IP会给出我们所需的频率输出,并计算必要的分频器、乘法器和相位参数实现所需的输出频率。

然而,如果我们有多个时钟,那么我们需要分别计算这些寄存器的值并单独更新时钟寄存器(每个时钟有两个寄存器)。

这里有个注意点就是在进行时钟更改前最好等待IP锁定到之前的频率后再进行新操作。

更改频率的代码还是比较简单的,如下:

代码语言:javascript
复制
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"

#include "xclk_wiz.h"

XClk_Wiz ClkWiz_Dynamic;
XClk_Wiz_Config *CfgPtr_Dynamic;

#define XCLK_WIZARD_DEVICE_ID  XPAR_CLK_WIZ_0_DEVICE_ID
#define XCLK_US_WIZ_RECONFIG_OFFSET 0x0000025C
#define CLK_LOCK   1

int main()
{
    init_platform();
    int Status;
    print("Hello World\n\r");

    CfgPtr_Dynamic = XClk_Wiz_LookupConfig(XCLK_WIZARD_DEVICE_ID);
 XClk_Wiz_CfgInitialize(&ClkWiz_Dynamic, CfgPtr_Dynamic,     
                        CfgPtr_Dynamic->BaseAddr);

 while(1){
  XClk_Wiz_WriteReg(CfgPtr_Dynamic->BaseAddr, 
                    XCLK_WIZ_REG25_OFFSET, 0);
  XClk_Wiz_SetRate(&ClkWiz_Dynamic, 10);
  XClk_Wiz_WriteReg(CfgPtr_Dynamic->BaseAddr, 
                     XCLK_US_WIZ_RECONFIG_OFFSET,   
                    (XCLK_WIZ_RECONFIG_LOAD | 
                    XCLK_WIZ_RECONFIG_SADDR));
  Status = XClk_Wiz_WaitForLock(&ClkWiz_Dynamic);
  usleep(10000000);
  XClk_Wiz_WriteReg(CfgPtr_Dynamic->BaseAddr, 
                    XCLK_WIZ_REG25_OFFSET, 0);
  XClk_Wiz_SetRate(&ClkWiz_Dynamic, 14);
  XClk_Wiz_WriteReg(CfgPtr_Dynamic->BaseAddr, 
             XCLK_US_WIZ_RECONFIG_OFFSET, 
            (XCLK_WIZ_RECONFIG_LOAD |    
            XCLK_WIZ_RECONFIG_SADDR));
  Status = XClk_Wiz_WaitForLock(&ClkWiz_Dynamic);
  usleep(10000000);
 }
    cleanup_platform();
    return 0;
}

当然,我们也可以使用类似的方法,通过将时钟频率降低来实现不同功耗模式下 FPGA 的功耗,从而实现降低功耗的功能。

参考文献

❝https://blog.csdn.net/qq_31799983/article/details/109407898 ❞

❝https://www.adiuvoengineering.com/post/microzed-chronicles-dynamic-clocking ❞

❝https://docs.xilinx.com/r/en-US/pg065-clk-wiz ❞

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenFPGA 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考文献
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档