FPGA 時鐘分頻

2021-08-04 23:34:53 字數 3894 閱讀 2421

時鐘訊號的處理是fpga的特色之一,因此分頻器也是fpga設計中使用頻率非常高的基本設計之一。一般在fpga中都有整合的鎖相環可以實現各種時鐘的分頻和倍頻設計,但是通過語言設計進行時鐘分頻是最基本的訓練,在對時鐘要求不高的設計時也能節省鎖相環資源。在本實驗中我們將實現任意整數的分頻器,分頻的時鐘保持50%占空比。 

1,偶數分頻:偶數倍分頻相對簡單,比較容易理解。通過計數器計數是完全可以實現的。如進行n倍偶數分頻,那麼通過時鐘觸發計數器計數,當計數器從0計數到n/2-1時,輸出時鐘進行翻轉,以此迴圈下去。 

總結如下:對於實現占空比為50%的n倍奇數分頻,首先進行上公升沿觸發進行模n計數,計數選定到某乙個值進行輸出時鐘翻轉,然後經過(n-1)/2再次進行翻轉得到乙個占空比非50%奇數n分頻時鐘。再者同時進行下降沿觸發的模n計數,到和上公升沿觸發輸出時鐘翻轉選定值相同值時,進行輸出時鐘時鐘翻轉,同樣經過(n-1)/2時,輸出時鐘再次翻轉生成占空比非50%的奇數n分頻時鐘。兩個占空比非50%的n分頻時鐘進行邏輯運算(正週期多的相與,負週期多的相或),得到占空比為50%的奇數n分頻時鐘。 

//輸入訊號,其中clk連線到fpga的c1腳,頻率為12mhz

output clkout;

//輸出訊號,可以連線到led觀察分頻的時鐘

//parameter是verilog裡常數語句

parameter width =3;

//計數器的位數,計數的最大值為 2**width-1

parameter n =5;

//分頻係數,請確保 n < 2**width-1,否則計數會溢位

reg[width-1:

0] cnt_p,cnt_n;

//cnt_p為上公升沿觸發時的計數器,cnt_n為下降沿觸發時的計數器

reg clk_p,clk_n;

//clk_p為上公升沿觸發時分頻時鐘,clk_n為下降沿觸發時分頻時鐘

//上公升沿觸發時計數器的控制

always@(

posedge clk or

negedge rst_n )

//posedge和negedge是verilog表示訊號上公升沿和下降沿

//當clk上公升沿來臨或者rst_n變低的時候執行一次always裡的語句

beginif(

!rst_n)

cnt_p<=0;

else

if(cnt_p==

(n-1))

cnt_p<=0;

else cnt_p<=cnt_p+1;

//計數器一直計數,當計數到n-1的時候清零,這是乙個模n的計數器

end//上公升沿觸發的分頻時鐘輸出,如果n為奇數得到的時鐘占空比不是50%;如果n為偶數得到的時鐘占空比為50%

always@(

posedge clk or

negedge rst_n)

beginif(

!rst_n)

clk_p<=0;

else

if(cnt_p<

(n>>1)

)//n>>1表示右移一位,相當於除以2去掉餘數

clk_p<=0;

else

clk_p<=1;

//得到的分頻時鐘正週期比負週期多乙個clk時鐘

end//下降沿觸發時計數器的控制

always@(

negedge clk or

negedge rst_n)

beginif(

!rst_n)

cnt_n<=0;

else

if(cnt_n==

(n-1))

cnt_n<=0;

else cnt_n<=cnt_n+1;

end//下降沿觸發的分頻時鐘輸出,和clk_p相差半個時鐘

always@(

negedge clk)

beginif(

!rst_n)

clk_n<=0;

else

if(cnt_n<

(n>>1)

) clk_n<=0;

else

clk_n<=1;

//得到的分頻時鐘正週期比負週期多乙個clk時鐘

endassign clkout =

(n==1)

?clk:

(n[0])

?(clk_p&clk_n)

:clk_p;

//條件判斷表示式

//當n=1時,直接輸出clk

//當n為偶數也就是n的最低位為0,n(0)=0,輸出clk_p

//當n為奇數也就是n最低位為1,n(0)=1,輸出clk_p&clk_n。正週期多所以是相與

endmodule

測試檔案,進行功能**時需要編寫testbench測試檔案。verilog裡的testbench檔案和原始檔一樣也是.v檔案,**能讓我們更直觀的觀察訊號波形,可以先閱讀diamond的使用了解如何使用diamond中整合的**工具。

`timescale

1ns/

100ps

//**時間單位/時間精度,時間單位要大於或者等於時間精度

module divide_tb();

//測試檔案也是乙個module,因為用於**所以無需輸入輸出訊號

reg clk,rst_n;

//需要產生的激勵訊號定義,激勵訊號需要過程塊產生所以定義為reg型變數

wire clkout;

//需要觀察的輸出訊號定義,定義為wire型變數

//初始化過程塊

initial

begin

clk =0;

rst_n =0;

#25//#表示延時25個時間單位

rst_n =1;

//產生了乙個初始25ns低電平,然後變高電平的復位訊號

endalways

#10 clk =

~clk;

//每隔10ns翻轉一次clk訊號,也就是產生乙個時鐘週期20ns的clk,頻率為50mhz

//module呼叫例化格式

divide #

(.width(4)

,.n(11)

) u1 (

//#後面的()中為引數傳遞,如果不傳遞引數就是所呼叫模組中的引數預設值

//divide表示所要例化的module名稱,u1是我們定義的例化名稱,必須以字母開頭

.clk (clk)

,//輸入輸出訊號連線。 .clk表示module本身定義的訊號名稱;(clk)表示我們在這裡定義的激勵訊號

.rst_n (rst_n)

,//在testbench裡定義的訊號名稱可以與所要呼叫module的埠訊號名稱不同

.clkout (clkout));

endmodule

時鐘為12mhz。你可以通過**波形觀察分頻時鐘(注意**的時間是有限的,所以分頻時鐘頻率需要較高)。如果我們想通過眼睛觀察led的閃爍,那麼需要設定引數n和width得到乙個頻率較低的時鐘(例如n=12000000,width=24,分頻時鐘週期為1秒)。 

訊號引腳

clkc1

rst_n

l14clkout

n13

修改程式中的分頻係數和計數器位數就能夠調整led閃爍速度(注意計數的最大值一定要保證超過分頻係數n)。 

關於FPGA的時鐘分頻問題

關於fpga的時鐘分頻問題 在fpga裡面,關於時鐘分頻,可以通過鎖相環來實現,但是,鎖相環的分頻系統受到一定的限制 根據所用的fpga晶元不同,所受到的限制也不一樣 不能隨心所欲的按照自己的想法來分頻。所以,我們可以自己寫乙個分頻的程式,當然,能夠達到分頻的效果,只是精度並沒有像pll的那麼高,但...

Verilog 時鐘偶分頻 奇分頻 任意分頻

分頻器是指使輸出訊號頻率為輸入訊號頻率整數分之一的電子電路。偶分頻計數器 偶分頻比較簡單,假設為n分頻,只需計數到n 2 1,然後時鐘翻轉 計數清零,如此迴圈就可以得到n 偶 分頻。如下 module even divider clk in,rst n,even en,偶分頻使能訊號,方便後續設計任...

FPGA奇數分頻

前注 設計中盡量還是要避免使用自己計數分頻得到的時鐘,去使用廠家自帶的分頻ip 如vivado中的clock wizard 偶數分頻比較簡單,這裡略過。對於不要求占空比為50 的奇數分頻,也比較簡單,直接模n計數,期間進行兩次翻轉就可以了。這裡重點介紹要求占空比為50 的奇數分頻。步驟 1.在時鐘上...