ZYNQ笔记(二十):Clocking Wizard 动态配置

版本:Vivado2020.2(Vitis)

任务:ZYNQ PS端 通过 AXI4Lite 接口配置 Clocking Wizard IP核输出时钟频率

目录

一、介绍

二、寄存器定义

三、配置

四、PS端代码


一、介绍

Xilinx 的 Clock Wizard IP核 用于在 FPGA 中生成和管理时钟信号。它支持 动态重配置(Dynamic Reconfiguration) ,允许在运行时通过 AXI4-Lite 接口DRP 接口(这两个接口都是在配置IP核时的可选接口) 修改时钟参数(如频率、相位等),而无需重新编程 FPGA。

  • AXI4-Lite 接口:用于软件(如 MicroBlaze/Zynq PS)动态修改时钟参数

  • DRP(Dynamic Reconfiguration Port):硬件接口,直接访问 Clock Wizard 配置寄存器

二、寄存器定义

参考文章:

AMD Technical Information Portal

[小梅哥FPGA] 如何通过动态重配置实现FPGA时钟的实时频率/相位/占空比调整?

如何使用AXI4接口对PLL/MMCM输出时钟的频率和相位进行动态重配置 - Xilinx Vivado 开发板 - 芯路恒电子技术论坛 - Powered by Discuz!

每个寄存器数据为32位4字节,大部分寄存器地址间隔0x04。

|---------------------------------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 寄存器名 | 寄存器地址 | 功能 |
| Software Reset Register (SRR) | C_BASEADDR+0X00 | 写入0x0000_000A可复位PLL/MMCM |
| Status Register (SR) | C_BASEADDR+0X04 | Locked信号,Bit[0] = locked,值为1时代表输出时钟稳定 |
| Clock Configuration Register 0 | C_BASEADDR+0X200 | 反馈时钟分、倍频控制,value = 系数*1000 Bit[25:16] = CLKFBOUT_FRAC Multiply(仅MMCM才有,VCO的1/8小数倍频系数) Bit[15:8] = CLKFBOUT_MULT(VCO整数倍频系数) Bit[7:0] = DIVCLK_DIVIDE(VCO分频系数) |
| Clock Configuration Register 1 | C_BASEADDR+0X204 | 反馈时钟相位控制,value = 相位*1000 Bit[31:0] = CLKFBOUT_PHASE |
| Clock Configuration Register 2 | C_BASEADDR+0X208 | CLKOUT0分频系数,value = 分频系数*1000 Bit[7:0] = CLKOUT0_DIVIDE Bit[17:8] = CLKOUT0_FRAC Divide(仅MMCM才有,CLKOUT0的1/8小数倍频系数) |
| Clock Configuration Register 3 | C_BASEADDR+0X20C | CLKOUT0相位配置,value = 相位*1000 Bit[31:0] = CLKOUT0_PHASE |
| Clock Configuration Register 4 | C_BASEADDR+0X210 | CLKOUT0占空比配置,value = 占空比*1000 Bit[31:0] = CLKOUT0_DUTY |
| Clock Configuration Register 5 | C_BASEADDR+0X214 | CLKOUT1分频系数,不支持小数分频,value = 分频系数*1000 Bit[7:0] = CLKOUT1_DIVIDE |
| ...... | ...... | ...... |
| Clock Configuration Register 23 | C_BASEADDR+0X25C | Bit[0] = LOAD, 置 1 加载配置寄存器的值到内部寄存器,并在下一周期置0 Bit[1] = SADDR, 写 0 将默认 GUI 中的参数加载到动态配置中; 写 1 将配置寄存器参数加载到动态配置中 |

三、配置

本次通过 ZYNQ PS 端进行配置, Clocking Wizard 配置如下:MMCM、勾选动态配置(频率配置)、AXI4Lite 接口(PS 通过该接口配置)、输入频率100MHz(根据实际频率设置)

四、PS端代码

参考的正点原子的代码,并他的基础上进行修改,因为源码实现只有一个输出时钟端口的 clk_wiz 的频率配置,修改为有两个时钟输出端口的 clk_wiz 频率配置,(但是我发现正点原子的小数部分设置没有除以8,我测试输出时钟输入给 DVI 转化模块驱动 HDMI 时,除以8后才对上时序频率,显示屏才出现图像,但是正点原子的驱动 LCD 的例程都没有除以8,可能存在精度问题,希望有搞清楚的可以在评论区补充一下):

clk_wiz.h:

cs 复制代码
#ifndef CLK_WIZ_H_
#define CLK_WIZ_H_

#include "xil_types.h"

#define CLK_SR_OFFSET    0x04    //Status Register

//clk_out0
#define CLK_CFG0_OFFSET  0x200   //Clock Configuration Register 0
#define CLK_CFG2_OFFSET  0x208   //Clock Configuration Register 2

//clk_out1
#define CLK_CFG5_OFFSET  0x214   //Clock Configuration Register 5
#define CLK_CFG7_OFFSET  0x222   //Clock Configuration Register 7

#define CLK_CFG23_OFFSET 0x25C   //Clock Configuration Register 23

void clk_wiz_cfg(u32 clk_device_id, double freq0, double freq1);

#endif /* CLK_WIZ_H_ */

clk_wiz.c

cs 复制代码
#include "xclk_wiz.h"
#include "clk_wiz.h"
#include "xparameters.h"

#define CLK_WIZ_IN_FREQ 100  //时钟IP核输入100Mhz

XClk_Wiz clk_wiz_inst;       //时钟IP核驱动实例

//时钟IP核动态重配置
//参数1:时钟IP核的器件ID
//参数2:时钟IP核输出的时钟0频率 单位:MHz
//参数3:时钟IP核输出的时钟1频率 单位:MHz
void clk_wiz_cfg(u32 clk_device_id, double freq0, double freq1)
{
	double div_factor = 0;
	u32 div_factor_int = 0;
	u32 dviv_factor_frac = 0;
	u32 clk_divide = 0;
	u32 status = 0;

	//初始化XCLK_Wiz
	XClk_Wiz_Config *clk_cfg_ptr;
	clk_cfg_ptr = XClk_Wiz_LookupConfig(clk_device_id);
	XClk_Wiz_CfgInitialize(&clk_wiz_inst,clk_cfg_ptr,clk_cfg_ptr->BaseAddr);

	//配置输入时钟倍频/分频系数(多个时钟输出就只用配置一次,后面都用这一个标准进行分配输出)
	XClk_Wiz_WriteReg(clk_cfg_ptr->BaseAddr,CLK_CFG0_OFFSET,0x00000a01);  //10倍频,1分频(输出频率不能超过(CLK_WIZ_IN_FREQ*10/1)MHz)

	//配置输出时钟0频率
	if(freq0 <= 0){
		//计算分频系数
		div_factor 			= CLK_WIZ_IN_FREQ * 10 / freq0;
		div_factor_int 		= (u32)div_factor;								  //(取整)分频系数整数部分
		dviv_factor_frac 	= (u32)((div_factor - div_factor_int) * 1000 /8); //(取整)分频系数小数部分的8分之一(针对mmcm)
		clk_divide 			= div_factor_int | (dviv_factor_frac<<8);
		xil_printf("div_factor_0: %d.%d\n", div_factor_int,dviv_factor_frac*8); // 打印设置的分频系数
		//配置分频系数
		XClk_Wiz_WriteReg(clk_cfg_ptr->BaseAddr,CLK_CFG2_OFFSET,clk_divide);
	}

	//配置输出时钟0频率
	if(freq1 <= 0){
		//计算分频系数
		div_factor 			= CLK_WIZ_IN_FREQ * 10 / freq1;
		div_factor_int 		= (u32)div_factor;
		dviv_factor_frac	= (u32)((div_factor - div_factor_int) * 1000 /8);
		clk_divide 			= div_factor_int | (dviv_factor_frac<<8);
		xil_printf("div_factor_1: %d.%d\n", div_factor_int,dviv_factor_frac*8); // 打印设置的分频系数
		//配置分频系数
		XClk_Wiz_WriteReg(clk_cfg_ptr->BaseAddr,CLK_CFG7_OFFSET,clk_divide);
	}

	// 调试(可选):打印当前寄存器值
	/*xil_printf("After config:\n");
	xil_printf("CLK_CFG0: 0x%08X\n", XClk_Wiz_ReadReg(clk_cfg_ptr->BaseAddr, CLK_CFG0_OFFSET));
	xil_printf("CLK_CFG2: 0x%08X\n", XClk_Wiz_ReadReg(clk_cfg_ptr->BaseAddr, CLK_CFG2_OFFSET));
	xil_printf("CLK_CFG5: 0x%08X\n", XClk_Wiz_ReadReg(clk_cfg_ptr->BaseAddr, CLK_CFG5_OFFSET));
	xil_printf("CLK_CFG7: 0x%08X\n", XClk_Wiz_ReadReg(clk_cfg_ptr->BaseAddr, CLK_CFG7_OFFSET));*/

	//加载重配置的参数
	XClk_Wiz_WriteReg(clk_cfg_ptr->BaseAddr,CLK_CFG23_OFFSET,0x00000003);
	//获取时钟IP核的状态,判断是否重配置完成
	while(1){
		status = XClk_Wiz_ReadReg(clk_cfg_ptr->BaseAddr,CLK_SR_OFFSET);
		if(status&0x00000001)    //Bit0 Locked信号
			return ;
	}
}

函数调用

cs 复制代码
#include "xclk_wiz.h"
#include "clk_wiz.h"

#define CLK_WIZ_ID      XPAR_CLK_WIZ_0_DEVICE_ID    //时钟IP核器件ID

int main()
{
	double freq0 = 74.25;
    double freq1 = 371.25;

	//配置时钟IP输出频率(单位MHz)
	clk_wiz_cfg(CLK_WIZ_ID, freq0 , freq1);

	...

	return 0;
}
相关推荐
大白的编程日记.19 分钟前
【Linux学习笔记】理解一切皆文件实现原理和文件缓冲区
linux·笔记·学习
孞㐑¥20 分钟前
Linux之进程控制
linux·开发语言·c++·经验分享·笔记
Alessio Micheli38 分钟前
奇怪的公式
笔记·线性代数
愚润求学43 分钟前
【Linux】简单设计libc库
linux·运维·开发语言·c++·笔记
chennalC#c.h.JA Ptho1 小时前
Bodhi linux 系统详解
linux·经验分享·笔记·系统架构·系统安全
zhuziheniaoer1 小时前
rust-candle学习笔记11-实现一个简单的自注意力
笔记·学习·自然语言处理·rust
碎碎思1 小时前
FPGA+ESP32 = GameBoy 是你的童年吗?
fpga开发
LAM LAB2 小时前
【WIN】笔记本电脑忘记密码解决办法/笔记本电脑重装系统笔记/bitlocker忘记密码的解决办法
笔记·电脑
lwewan2 小时前
26考研——中央处理器_指令执行过程(5)
笔记·考研
搬砖的小码农_Sky2 小时前
FPGA:XILINX FPGA产品线以及器件选型建议
嵌入式硬件·fpga开发·硬件架构·硬件工程