分頻分為偶分頻和奇分頻。
分頻器從某種程度上來講是計數(shù)器有計劃的輸出。
1.偶數(shù)倍分頻:偶數(shù)倍分頻應(yīng)該是大家都比較熟悉的分頻,通過計數(shù)器計數(shù)是完全可以實現(xiàn)的。如進行N倍偶數(shù)分頻,那么可以通過由待分頻的時鐘觸發(fā)計數(shù)器計數(shù),當(dāng)計數(shù)器從0計數(shù)到N/2-1時,輸出時鐘進行翻轉(zhuǎn),并給計數(shù)器一個復(fù)位信號,使得下一個時鐘從零開始計數(shù)。以此循環(huán)下去。這種方法可以實現(xiàn)任意的偶數(shù)分頻。
2.奇數(shù)倍分頻:
A、第一種比較簡單的辦法,通過計數(shù)器來實現(xiàn)。如進行三分頻,通過待分頻時鐘上升沿觸發(fā)計數(shù)器進行模三計數(shù),當(dāng)計數(shù)器計數(shù)到0的時候輸出的時鐘翻轉(zhuǎn)一次,當(dāng)計數(shù)器計數(shù)到2(1也是可以的,只要在0-2之間輸出時鐘變化一次即可)的時候再翻轉(zhuǎn)一次這樣就可實現(xiàn)三分頻,不過這種方法得到的時鐘占空比不是那么的優(yōu)美,是1/3或者是2/3。下面是對應(yīng)的三分頻verilog代碼和相應(yīng)的testbench代碼。
//三分頻,占空比不是50%。 module?div_3?(q,clk,reset); ????output?q; ????input?reset; ????input?clk; ????reg?q; ????reg?[1:0]?count;???//?設(shè)了一個2位的計數(shù)器可以從0計數(shù)到2; always?@?(posedge?clk?or?posedge?reset)???//?同步復(fù)位,上升沿有效 ????if?(reset)???????????????????????????//?復(fù)位 ??????begin ????????q<=1'b0; ????????count<=2'b00; ??????end ????else?if(count==0)????????????????//?第一個CLK上升沿來的時候q翻轉(zhuǎn)一次計數(shù)器加一; ??????begin ????????q<=~q; ????????count<=count+1'b1; ??????end ????else?if(count==2)??????????????//第3個CLK上升沿來的時候輸出q翻轉(zhuǎn)一次計數(shù)器歸零; ??????begin ????????q=~q; ????????count<=2'b00;???????????????//把計數(shù)復(fù)位 ??????end ????else?????????????????????????????????//???第二個CLK上升沿來的時候q不動作,計數(shù)器加一。??? ??????begin ????????count<=count+1'b1; ??????end endmodule
//測試代碼(testbench)適合xilinx的vivado module?test; ????reg?clk; ????reg?reset; ????wire?q; ???? ????div_3?d3?(q,clk,reset); always?#20?clk=~clk; ????initial ??????begin ????????clk=1'b0; ????????reset=1'b1; ????????#24?reset?=1'b0; ??????end endmodule
下面是仿真出來的結(jié)果,最后輸出的時鐘的周期是原來時鐘周期的三倍,但是唯一不同的地方就是占空比不是50%。
B、如果對于自己的結(jié)果不是很滿意,可以再搞一個占空比是50%的出來,先把原理講一下:
1)首先,如果我們同時利用時鐘的上升沿和下降沿來制作一個分頻器,這個只是理論上的,一般不用這種方法。
? ? ?我們還是來整三分頻的分頻器。用一個3模的計數(shù)器,時鐘的上上沿和下降沿都計數(shù),那么當(dāng)計數(shù)器從0計數(shù)到2的時候輸出時鐘就會翻轉(zhuǎn)一次,計數(shù)器復(fù)位,然后等待計數(shù)3次之后再翻轉(zhuǎn)一次,計數(shù)器復(fù)位。用代碼表示是這個樣子的。
always?@(?posedge?clk?or?negedge?clk)??//時鐘的上升沿河下降沿都有效 ??if(reset) ????begin ???????k<=0; ???????clk_3<=0; ????end ?else ?if(k==2)????//計數(shù)到3個邊沿之后。輸出時鐘就會翻轉(zhuǎn)一次。 ????begin ???????k<=0; ???????clk_3<=~clk_3; ????end ?else ????k<=k+1;
2)接下來搞一種用“”或“”邏輯來實現(xiàn)奇數(shù)分頻的技術(shù)。
? ? ? 接著來玩兒三分頻的計數(shù)器。
? ? ??
module?fdiv(?clk,?reset_n,?clkout?); input????clk; input????reset_n; output???clkout; reg?[1:0]??count; reg????????div1; reg????????div2; wire???????clkout; always?@(posedge?clk) begin if?(?reset_n?) ???????count?<=?2'b00; else ???????case?(?count?) ?????????2'b00?:?count?<=?2'b01; ?????????2'b01?:?count?<=?2'b10; ?????????2'b10?:?count?<=?2'b00; ?????????default?: ???????????????????count?<=?2'b00; ???????endcase end always?@(?posedge?reset_n?or?posedge?clk?)?//the?first?divder?module. begin if?(???reset_n?) ???????div1?<=?1'b1;???//this?is?the?first?problem?that?I?wanna?to?solve,?because?I?just?wondering?the?"1"?cannot?make?a?high?level. ?else?if?(?count?==?2'b00?) ???????div1?<=?~?div1; end always?@(?posedge?reset_n?or???negedge?clk?)??//the?second?divder?module. begin if?(?reset_n?) ???????div2?<=?1'b1; else?if?(?count?==?2'b10?) ???????div2?<=?~?div2; end assign?clkout?=?div1?^?div2; endmodule
這是驗證代碼
`timescale?1ns/1ns //`include?"fdiv.v" module?fsim(); ????reg?clk;??????????//input??對應(yīng)的端口應(yīng)當(dāng)申明為?reg, ????reg?reset_n; ????wire?clkout;???????//output?對應(yīng)的端口申明為?wire, ???//?wire[2:0]?div1;??//怎么讓結(jié)果里面顯示出來中間的一些變量的變化 ???? ????fdiv?fdiv(?clk,?reset_n,?clkout?); ????always?#20?clk=~clk; ???? ????initial ????begin ????????clk=1'b0; ????????reset_n=1'b1; ????????#40?reset_n?=1'b0; ????end endmodule