FC2カウンター FPGAの部屋 Clocking Wizard の Dynamic Reconfiguration mode を使ってみよう1
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Clocking Wizard の Dynamic Reconfiguration mode を使ってみよう1

Clocking Wizard の Dynamic Reconfiguration mode を使ってみよう。つまり PLL の出力周波数をソフトウェアで動的に変更する機能だ。

なお、この記事は、Adom Taylor さんの”MicroZed Chronicles: Dynamic Clocking”を参照している。

ZYBO Z7-10 用の Dynamic_Clocking プロジェクトを Vivado 2022.2 で作成した。
Dynamic_Clocking_1_230526.png

MicroZed Chronicles: Dynamic Clocking”を参考にしてブロック・デザインを作成し、それにカウンタを追加してカウント値から Clocking Wizard のクロック出力の周波数を推定する。
なお、CDC は考えていない。簡易的な用途だということでお目こぼし願いたい。
Dynamic Clocking ブロック・デザインを示す。
Dynamic_Clocking_2_230526.png

processing_system7_0 の FCLK_CLK0 の動作周波数は 100 MHz に設定した。
Dynamic_Clocking_3_230526.png

Clocking Wizard の設定を示す。
Clocing Options タブでは Dynamic Reconfig にチェックを入れてある。
Dynamic_Clocking_4_230526.png

Output Clocks タブでは、clk_out1 を 40 MHz に設定した。
Dynamic_Clocking_5_230526.png

Address Editor 画面を示す。
Dynamic_Clocking_6_230526.png

HDL Wrapper を作成して、論理合成、インプリメンテーション、ビットストリームの生成を行った。
Project Summary を示す。
Dynamic_Clocking_7_230526.png

ハードウェアをエクスポートして、Vitis 2022.2 を起動した。
DC_wrapper プラットフォームと Dynamic_Clocking アプリケーション・プロジェクトを作成した。
Dynamic_Clocking アプリケーション・プロジェクトをビルドして、成功した。
Dynamic_Clocking_8_230526.png

Dynamic_Clocking アプリケーション・プロジェクトを実行したところ、Tera Term に結果が表示された。
Dynamic_Clocking_9_230526.png

最初の 1 秒間のカウントは 40000019 だった。この時は、40 MHz の出力周波数だった。

次に XClk_Wiz_SetRate(&ClkWiz_Dynamic, 10); で 10 MHz にしたときの 1 秒間のカウントは 10958909 だった。10.96 MHz 位とすると、結構ずれている気がする。

3 番目に XClk_Wiz_SetRate(&ClkWiz_Dynamic, 25); で 25 MHz にしたときの 1 秒間のカウントは 25806462 だった。25.81 MHz 位とすると、こちらも結構ずれている気がする。

4 番目に細かい周波数の設定がしたくて XClk_Wiz_SetRateHz(&ClkWiz_Dynamic, 20000000); で 20 MHz に設定したつもりだったが、1 秒間のカウントは 25806465 だった。3 番目の設定値から変更されていないようだ。

アプリケーション・ソフトウェアの Dynamic_Clocking.c を貼っておく。

// Dynamic_Clocking.c
// 2023/05/18 by marsee
// Referred to "MicroZed Chronicles: Dynamic Clocking"
// https://www.adiuvoengineering.com/post/microzed-chronicles-dynamic-clocking

#include <stdio.h>
#include "xclk_wiz.h"
#include "xgpio.h"
#include "xparameters.h"

XClk_Wiz ClkWiz_Dynamic;
XClk_Wiz_Config *CfgPtr_Dynamic;
XGpio gpio_0, gpio_1;

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

int main(){
    u32 count, locked;
    int Status;

    CfgPtr_Dynamic = XClk_Wiz_LookupConfig(XCLK_WIZARD_DEVICE_ID);
    XClk_Wiz_CfgInitialize(&ClkWiz_Dynamic, CfgPtr_Dynamic, CfgPtr_Dynamic->BaseAddr);
    XGpio_Initialize(&gpio_0, XPAR_AXI_GPIO_0_DEVICE_ID);
    XGpio_Initialize(&gpio_1, XPAR_AXI_GPIO_1_DEVICE_ID);

    printf("freq = 40 MHz\n");
    XGpio_DiscreteWrite(&gpio_1, 1, 1); // counter SCLR = 1, CE = 0
    usleep(1000);
    XGpio_DiscreteWrite(&gpio_1, 1, 2); // counter SCLR = 0, CE = 1
    sleep(1);
    XGpio_DiscreteWrite(&gpio_1, 1, 0); // counter SCLR = 0, CE = 0
    count = XGpio_DiscreteRead(&gpio_0, 1);
    locked = XGpio_DiscreteRead(&gpio_0, 2);
    printf("count = %d, locked = %d\n\n", count, locked);

    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);
    printf("freq = 10 MHz, XClk_Wiz_SetRate\n");
    XGpio_DiscreteWrite(&gpio_1, 1, 1); // counter SCLR = 1, CE = 0
    usleep(1000);
    XGpio_DiscreteWrite(&gpio_1, 1, 2); // counter SCLR = 0, CE = 1
    sleep(1);
    XGpio_DiscreteWrite(&gpio_1, 1, 0); // counter SCLR = 0, CE = 0
    count = XGpio_DiscreteRead(&gpio_0, 1);
    locked = XGpio_DiscreteRead(&gpio_0, 2);
    printf("count = %d, locked = %d\n\n", count, locked);

    XClk_Wiz_WriteReg(CfgPtr_Dynamic->BaseAddr, XCLK_WIZ_REG25_OFFSET, 0);
    XClk_Wiz_SetRate(&ClkWiz_Dynamic, 25);
    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);
    printf("freq = 25 MHz\n");
    XGpio_DiscreteWrite(&gpio_1, 1, 1); // counter SCLR = 1, CE = 0
    usleep(1000);
    XGpio_DiscreteWrite(&gpio_1, 1, 2); // counter SCLR = 0, CE = 1
    sleep(1);
    XGpio_DiscreteWrite(&gpio_1, 1, 0); // counter SCLR = 0, CE = 0
    count = XGpio_DiscreteRead(&gpio_0, 1);
    locked = XGpio_DiscreteRead(&gpio_0, 2);
    printf("count = %d, locked = %d\n\n", count, locked);

    XClk_Wiz_WriteReg(CfgPtr_Dynamic->BaseAddr, XCLK_WIZ_REG25_OFFSET, 0);
    XClk_Wiz_SetRateHz(&ClkWiz_Dynamic, 20000000);
    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);
    printf("freq = 20 MHz, XClk_Wiz_SetRateHz(&ClkWiz_Dynamic, 20000000);\n");
    XGpio_DiscreteWrite(&gpio_1, 1, 1); // counter SCLR = 1, CE = 0
    usleep(1000);
    XGpio_DiscreteWrite(&gpio_1, 1, 2); // counter SCLR = 0, CE = 1
    sleep(1);
    XGpio_DiscreteWrite(&gpio_1, 1, 0); // counter SCLR = 0, CE = 0
    count = XGpio_DiscreteRead(&gpio_0, 1);
    locked = XGpio_DiscreteRead(&gpio_0, 2);
    printf("count = %d, locked = %d\n\n", count, locked);

    return(0);
}

  1. 2023年05月26日 04:32 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/5945-d2745733
この記事にトラックバックする(FC2ブログユーザー)