如何在 Zynq PS 端使用 wiz_clk 动态配置:

首先,您需要在 Vivado 中创建一个包含 wiz_clk 的设计。这通常包括:

Zynq Processing System (PS)

Clocking Wizard (wiz_clk)

AXI Interconnect(如果需要访问 PL 中的其他 IP)

配置 Clocking Wizard (wiz_clk) 以根据您的硬件需求生成所需的时钟。

在 Vivado 中生成 Bitstream,并导出硬件描述文件(例如,用于 PetaLinux 的 .hdf 文件)。

使用 PetaLinux 创建一个项目,并使用导出的硬件描述文件。

在 PetaLinux 项目中的设备树文件(system-user.dtsi)中,确保已添加 Clocking Wizard 的节点:

Copy

&clk_wiz_0 {

    status = "okay";

};

编译并部署 PetaLinux 镜像到 Zynq 设备。

在 PetaLinux 中,编写一个 C 程序(例如 clock_config.c),以动态配置 wiz_clk。

// Constants for Zynq-7020 PLL hardware parameters // Reference: Xilinx Zynq-7000 SoC Technical Reference Manual (UG585)

#define MIN_VCO_FREQ 600.0

// Minimum VCO frequency in MHz

#define MAX_VCO_FREQ 1200.0

// Maximum VCO frequency in MHz

#define MIN_CLKFBOUT_MULT 2

// Minimum CLKFBOUT multiplier value

#define MAX_CLKFBOUT_MULT 64

// Maximum CLKFBOUT multiplier value

#define MIN_DIVCLK_DIVIDE 1 // Minimum input clock divider value

#define MAX_DIVCLK_DIVIDE 106 // Maximum input clock divider value

#define MIN_OUTPUT_FREQ 10.0 // Minimum output frequency in MHz

#define MAX_OUTPUT_FREQ 800.0 // Maximum output frequency in MHz

// Calculate the register value for a given output frequency

unsigned int calculate_clk_wiz_reg_value(double input_freq, double output_freq) {

    unsigned int clkout0_divide = 1;

    unsigned int clkfbout_mult = 1;

    unsigned int divclk_divide = 1;

    double best_err = 1e9;

    double target_vco_freq = output_freq * clkout0_divide;

    for (unsigned int mult = MIN_CLKFBOUT_MULT; mult <= MAX_CLKFBOUT_MULT; ++mult) {

        for (unsigned int div = MIN_DIVCLK_DIVIDE; div <= MAX_DIVCLK_DIVIDE; ++div) {

            double vco_freq = input_freq * mult / div;

            if (vco_freq < MIN_VCO_FREQ || vco_freq > MAX_VCO_FREQ) {

                continue;

            }

            double err = fabs(vco_freq - target_vco_freq);

            if (err < best_err) {

                best_err = err;

                clkfbout_mult = mult;

                divclk_divide = div;

            }

        }

    }

    // Combine the calculated values into a single register value

    unsigned int clk_wiz_reg_value = (clkout0_divide << 8) | (clkfbout_mult << 16) | (divclk_divide << 24);

    return clk_wiz_reg_value;

}

int main() {

    double input_freq = 100.0; // Input frequency in MHz

    double output_freq_1 = 50.0; // Desired output frequency 1 in MHz

    double output_freq_2 = 75.0; // Desired output frequency 2 in MHz

    // Calculate the Clocking Wizard register value for the desired output frequencies

    unsigned int clk_wiz_reg_value_1 = calculate_clk_wiz_reg_value(input_freq, output_freq_1);

    unsigned int clk_wiz_reg_value_2 = calculate_clk_wiz_reg_value(input_freq, output_freq_2);

    if (clk_wiz_reg_value_1 != 0) {

        printf("Clocking Wizard register value for output frequency 1: 0x%08X\n", clk_wiz_reg_value_1);

        // ... (The rest of your original code here for output frequency 1)

    }

    if (clk_wiz_reg_value_2 != 0) {

        printf("Clocking Wizard register value for output frequency 2: 0x%08X\n", clk_wiz_reg_value_2);

        // ... (The rest of your original code here for output frequency 2)

    }

}

猜你喜欢

转载自blog.csdn.net/ls1300005/article/details/131586251