1. 程式人生 > 其它 >FPGA-分頻器

FPGA-分頻器

技術標籤:基礎篇——分頻器基礎篇——按鍵消抖fpga

                               FPGA-分頻器

當給你一個時鐘,你覺得頻率太快了,想進行就分頻,就會使用到我們的分頻器。非常簡單且實用,且寫的無聊。
寫給出總體程式碼
module div_frequency(

input clk_i,
input rst_n_i,
output div2_o,
output div3_o,
output div4_o,
output div8_o
);

reg div2_o_r;
[email protected](posedge clk_i or negedge rst_n_i)

begin
if(!rst_n_i)
div2_o_r<=1’b0;
else
div2_o_r<=~div2_o_r;
end

reg [1:0] div_cnt1;
[email protected](posedge clk_i or negedge rst_n_i)
begin
if(!rst_n_i)
div_cnt1<=2’b00;
else
div_cnt1<=div_cnt1+1’b1;
end

reg div4_o_r;
reg div8_o_r;

[email protected](posedge clk_i or negedge rst_n_i)

begin
if(!rst_n_i)
div4_o_r<=1’b0;
else if(div_cnt12’b00 || div_cnt12’b10)
div4_o_r<=~div4_o_r;
else
div4_o_r<=div4_o_r;
end

[email protected](posedge clk_i or negedge rst_n_i)
begin
if(!rst_n_i)
div8_o_r<=1’b0;
else if(div_cnt1==2’b00)
div8_o_r<=~div8_o_r;
else
div8_o_r<=div8_o_r;
end

reg [1:0] pos_cnt;
reg [1:0] neg_cnt;
[email protected](posedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
pos_cnt<=2’b00;
else if(pos_cnt==2’d2)
pos_cnt<=2’b00;
else
pos_cnt<=pos_cnt+1’b1;
end

[email protected](negedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
neg_cnt<=2’b00;
else if(neg_cnt==2’d2)
neg_cnt<=2’b00;
else
neg_cnt<=neg_cnt+1’b1;
end

reg div3_o_r0;
reg div3_o_r1;
[email protected](posedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
div3_o_r0<=1’b0;
else if(pos_cnt<2’d1)
div3_o_r0<=1’b1;
else
div3_o_r0<=1’b0;
end

[email protected](negedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
div3_o_r1<=1’b0;
else if(neg_cnt<2’d1)
div3_o_r1<=1’b1;
else
div3_o_r1<=1’b0;
end
reg div2hz_o_r;

assign div2_o=div2_o_r;
assign div3_o=div3_o_r0 | div3_o_r1;
assign div4_o=div4_o_r;
assign div8_o=div8_o_r;

endmodule

一,2分頻部分
reg div2_o_r;
[email protected](posedge clk_i or negedge rst_n_i)
begin
if(!rst_n_i)
div2_o_r<=1’b0;
else
div2_o_r<=~div2_o_r;
end
我們設輸入時鐘的週期為T,
由上面程式碼可知,每當輸入時鐘上升沿的時候,我們就會翻轉。輸入時鐘一個週期只有一個上升沿,那麼也就意味著2分頻高低電平持續時間是一個輸入時鐘週期T,則2分頻的週期就是2T。達到了分頻的效果。
(明明很簡單,寫的卻很羅裡吧嗦,還沒圖

二,四分頻
有了上面2分頻思想,四分頻不是有手就行
我們只需要將[email protected](posedge clk_i or negedge rst_n_i),這個裡面 clk_i換成我們已經寫好的2分頻,四分頻就出來了。那八分頻不也簡單的狠。
但是如果每次都那麼一個一個的寫,不是很麻煩嗎
那麼我就加個計數器
reg [1:0] div_cnt1;
[email protected](posedge clk_i or negedge rst_n_i)
begin
if(!rst_n_i)
div_cnt1<=2’b00;
else
div_cnt1<=div_cnt1+1’b1;
end

reg div4_o_r;
[email protected](posedge clk_i or negedge rst_n_i)
begin
if(!rst_n_i)
div4_o_r<=1’b0;
else if(div_cnt12’b00 || div_cnt12’b10)
div4_o_r<=~div4_o_r;
else
div4_o_r<=div4_o_r;
end
每當輸入時鐘上升沿,計數器開始計數,也就是每過T,我們開始計數,沒過2T我們來翻轉電平。那麼週期為4T。那麼
其他偶數分頻不是有手就行。
三,奇數分頻
我們以3分頻為例,為什麼呢?(因為上面寫了)

reg [1:0] pos_cnt;
reg [1:0] neg_cnt;
[email protected](posedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
pos_cnt<=2’b00;
else if(pos_cnt==2’d2)
pos_cnt<=2’b00;
else
pos_cnt<=pos_cnt+1’b1;
end

[email protected](negedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
neg_cnt<=2’b00;
else if(neg_cnt==2’d2)
neg_cnt<=2’b00;
else
neg_cnt<=neg_cnt+1’b1;
end

reg div3_o_r0;
reg div3_o_r1;
[email protected](posedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
div3_o_r0<=1’b0;
else if(pos_cnt<2’d1)
div3_o_r0<=1’b1;
else
div3_o_r0<=1’b0;
end

[email protected](negedge div2_o_r or negedge rst_n_i)
begin
if(!rst_n_i)
div3_o_r1<=1’b0;
else if(neg_cnt<2’d1)
div3_o_r1<=1’b1;
else
div3_o_r1<=1’b0;
end
assign div3_o=div3_o_r0 | div3_o_r1;
看了程式碼,我們三分頻是基於2分頻時鐘,有兩個計時器 pos_cnt;neg_cnt;
由程式碼我們可以看出,他們分別從二分頻的上升沿和下降沿開始從0到2計數(顯然時間間隔為T
div3_o_r0 和 div3_o_r1在pos_cnt;neg_cnt為0的時刻為1,在1,2時間為0。
則div3_o當出現0時為1,無0則為1
從0計數到2,時間為6T,則每個數字為持續時間為2T
我們將0用00計,則每個數字持續時間為T

pos_cnt001122001122001122001122
neg_cnt200112200112200112200112
div3_o1110001110001110001

(為什麼不畫個圖?顯然不會,而且圖多了,反而不好看)
顯然其週期為6T,是對2分頻時鐘進行三分頻。(以此內推)