時(shí)鐘是每個(gè) FPGA 設(shè)計(jì)的核心。如果我們正確地設(shè)計(jì)時(shí)鐘架構(gòu)、沒有 CDC 問題并正確進(jìn)行約束設(shè)計(jì),就可以減少與工具斗爭(zhēng)的時(shí)間。

但對(duì)于某些應(yīng)用,我們希望能夠更改某些IP中的時(shí)鐘頻率。其中一個(gè)例子是在圖像處理管道中,輸出分辨率可以動(dòng)態(tài)變化,從而需要改變像素時(shí)鐘。
眾所周知,我們可以在 Zynq SoC 和 Zynq MPSoC 中使用結(jié)構(gòu)時(shí)鐘并在運(yùn)行時(shí)更改結(jié)構(gòu)時(shí)鐘的頻率。但是,如果我們?cè)?Zynq 或 ZYNQ MPSoC 中使用 FPGA 或 PL,我們?nèi)匀豢梢允褂脛?dòng)態(tài)配置的時(shí)鐘向?qū)г谶\(yùn)行時(shí)更改頻率。
動(dòng)態(tài)配置時(shí)鐘允許我們使用 AXI 接口在運(yùn)行時(shí)更改時(shí)鐘頻率。

為了創(chuàng)建一個(gè)簡(jiǎn)單的示例,我們將實(shí)例化PS并將動(dòng)態(tài)配置時(shí)鐘IP連接到主 AXI 接口。我們將輸出時(shí)鐘連接到 IO 引腳,以便我們可以對(duì)其進(jìn)行觀察并查看頻率的變化。

上面的時(shí)鐘是我們打算使用的最大頻率,這樣可以確保時(shí)序約束和時(shí)序性能正確。下圖是我們這次demo的最終設(shè)計(jì)。

接下來我們將在 Vitis 中開發(fā)軟件,并且將在設(shè)計(jì)中的 IP 下看到相關(guān)驅(qū)動(dòng)及文檔。
開發(fā)這個(gè)IP的驅(qū)動(dòng)和其他 AXI Lite 接口一樣,需要對(duì)IP寄存器空間進(jìn)行寫入和讀取。
要更改時(shí)鐘頻率輸出,我們有兩種選擇。如果只生成一個(gè)時(shí)鐘,我們可以使用名為 SetRate 的函數(shù)。該函數(shù)將通過AXI Lite總線傳遞到IP中,IP會(huì)給出我們所需的頻率輸出,并計(jì)算必要的分頻器、乘法器和相位參數(shù)實(shí)現(xiàn)所需的輸出頻率。
然而,如果我們有多個(gè)時(shí)鐘,那么我們需要分別計(jì)算這些寄存器的值并單獨(dú)更新時(shí)鐘寄存器(每個(gè)時(shí)鐘有兩個(gè)寄存器)。
這里有個(gè)注意點(diǎn)就是在進(jìn)行時(shí)鐘更改前最好等待IP鎖定到之前的頻率后再進(jìn)行新操作。
更改頻率的代碼還是比較簡(jiǎn)單的,如下:
#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;
}
當(dāng)然,我們也可以使用類似的方法,通過將時(shí)鐘頻率降低來實(shí)現(xiàn)不同功耗模式下 FPGA 的功耗,從而實(shí)現(xiàn)降低功耗的功能。


參考文獻(xiàn)
?https://blog.csdn.net/qq_31799983/article/details/109407898
?
?https://www.adiuvoengineering.com/post/microzed-chronicles-dynamic-clocking文章來源:http://www.zghlxwxcb.cn/news/detail-529236.html
?
?https://docs.xilinx.com/r/en-US/pg065-clk-wiz文章來源地址http://www.zghlxwxcb.cn/news/detail-529236.html
?
到了這里,關(guān)于【Vivado那些事兒】動(dòng)態(tài)時(shí)鐘的使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!