免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
從計數(shù)器到分頻電路(完結(jié))

  本文介紹常見的電路——計數(shù)器,然后我們由計數(shù)器電路講解到分頻電路。


一、計數(shù)器


  (1)計數(shù)器代碼


  計數(shù)器,顧名思義就是在時鐘的節(jié)拍下進(jìn)行計數(shù),一個簡單的N位計數(shù)器的代碼如下所示,這個計數(shù)器從0計數(shù)到2^N - 1(共計數(shù)了2^N個數(shù),也就是N位計數(shù)器):



 1 module count#(parameter N=8)( 2 input clk, 3 input clear, 4 output[N-1:0] cnt_Q 5 ); 6 reg[N-1:0] cnt; 7 assign cnt_Q = cnt; 8  9 always@(posedge clk)10   if(clear)11     cnt <= 'h0;      //同步清 0,高電平有效12   else13     cnt <= cnt+1'b1; //加法計數(shù)14 15 endmodule


上述描述的計數(shù)器通過 clear 信號清除計數(shù)值,然后下一周期開始加 1 計數(shù);當(dāng)計數(shù)器計到能夠存儲的最大數(shù)值時, 例如本例為 8 個 1,即 8'hff 就會自動回到 0,然后開始下一輪計數(shù)。


綜合得帶的電路如下所示:



 


  (2)計數(shù)器改進(jìn)


  如果想要實現(xiàn) 0~k 范圍內(nèi)計數(shù),其中k ≠ 2^N ,可以將 always 語句修改為:



always@(posedge clk)    if(clear)        cnt <=  'h0;    //同步清 0,高電平有效    else if(cnt==K)        cnt <= 'h0;    else        cnt <= cnt+1'b1; //減法計數(shù)            


 


  


  前面是累加計數(shù),下面是一個既可以遞增也能遞減,且具備初始值裝載和復(fù)位的計數(shù)器,代碼如下所示:



 1 module updown_count#(parameter N=8)( 2     input clk, 3     input clear, 4     input load, 5     input up_down, 6     input [N-1:0] preset_D, 7     output[N-1:0] cnt_Q 8 ); 9 reg[N-1:0] cnt;10 assign cnt_Q = cnt;11 12 always@(posedge clk)13   if(clear)14     cnt <= 'h0;      //同步清 0,高電平有效15   else if(load)16     cnt <= preset_D; //同步預(yù)置17   else if(up_down)18     cnt <= cnt+1;    //加法計數(shù)19   else20     cnt <= cnt-1;    //減法計數(shù)21 22 endmodule


 


 


 


二、計數(shù)器的用途


  (1)基本的計數(shù)功能與分頻


  計數(shù)器的基本功能顧名思義就是計數(shù)了,用來計數(shù),產(chǎn)生某個信號等等。利用這個功能,可以實現(xiàn)信號的分頻,具體會在后面的分頻電路中進(jìn)行描述。


 ?。?)看門狗


  計數(shù)器其實就可以設(shè)計成看門狗。在初始狀態(tài)時,看門狗電路首先裝載一個大數(shù);當(dāng)狀態(tài)機(jī)或者程序開始運行后,看門狗開始倒計數(shù)。如果狀態(tài)機(jī)或程序運行正常,每隔一段時間應(yīng)發(fā)出指令或信號讓看門狗重新裝載一個大的初始值,并再次開始倒計數(shù)。如果看門狗減到 0 就認(rèn)為程序或狀態(tài)機(jī)沒有正常工作,就需要強(qiáng)制整個系統(tǒng)復(fù)位。


  上面的第二處改進(jìn)的計數(shù)器電路描述就是一個看門狗電路,只要加上 cnt==0 作為看門復(fù)位狀態(tài)即可;而 load 信號則是狀態(tài)機(jī)或軟件給出的喂狗動作。


 ?。?)特殊的有限狀態(tài)機(jī)


  當(dāng)狀態(tài)機(jī)要求沒有那么嚴(yán)格的時候,這個時候就可以用計數(shù)器的計數(shù)值當(dāng)做狀態(tài)機(jī)的狀態(tài),計數(shù)增加或者減少就是改變狀態(tài)。


 


 


三、分頻電路


  (1)簡單的計數(shù)器


  計數(shù)器實質(zhì)是對輸入的驅(qū)動時鐘進(jìn)行計數(shù),所以計數(shù)器在某種意義上講,等同于對時鐘進(jìn)行分頻。例如一個最大計數(shù)長度為N=2^n(從0計數(shù)到N-1)的計數(shù)器,也就是寄存器位數(shù)位n,那么寄存器最高位的輸出為N=2^n分頻,次高位為N/2分頻...例如下面的代碼:



 1 module test#(parameter N=3)( 2 input clk, 3 input rst_n, 4 output clk_div 5 ); 6  7 reg [N-1:0] div_reg        ;//分頻計數(shù)器 8 always @(posedge clk or negedge rst_n) 9     if (rst_n == 1'b0 )10         div_reg    <= 0 ;11     else 12         div_reg    <= div_reg + 1'b1 ;13 14 assign clk_div = div_reg[N-1] ;15 16 17 endmodule


 該代碼描述的將一個3位的計數(shù)器最高位輸出,也就是計數(shù)長度為8(計數(shù)從0~7)波形如下所示:


    


可以看到最高位的輸出為輸入時鐘的8分頻。


 


  當(dāng)N不是2的整數(shù)次冪時,即N≠2^n時,從0計數(shù)到N-1,其最高位作為時鐘輸出(占空比不一定為 1:1)是輸入時鐘的1/N,也就是N分頻。我們來舉個例子,比如最大計數(shù)長度為5的計數(shù)器,即從0計數(shù)到4后又返回0,那么需要定義一個三位的寄存器。寄存器的計數(shù)過程為:


  000-001-010-011-100-000-001-010-011-100-000-001-010-011-100-000-001-010-011-100······


我們?nèi)∽罡呶?,得到的信號變化就是?/span>


  0-0-0-0-1-0-0-0-0-0-1-0-0-0-0-1-0-0-0-0-1···


 代碼如下所示:



 1 module test#(parameter N=3)( 2 input clk, 3 input rst_n, 4 output clk_div 5 ); 6  7 reg [N-1:0] div_reg        ;//分頻計數(shù)器 8 always @(posedge clk or negedge rst_n) 9     if (rst_n == 1'b0 )10         div_reg    <= 0 ;11     else if(div_reg == 3'd4)//從0計數(shù)到4,然后返回到0,5分頻12         div_reg    <= 0;13     else14         div_reg    <= div_reg + 1'b1 ;15 16 assign clk_div = div_reg[N-1] ;17 18 19 endmodule


 


仿真波形如下所示:


      


由此可以看到,每一個分頻后的時鐘周期=5倍原來的時鐘周期,因此是5分頻。


 


  那么這個情況是不是也可以包含第一種情況呢?我們那設(shè)置為8分頻看看,即前面的3'd4改成3'd7,得到的仿真波形如下所示:


      


可以看到,計數(shù)器的最高位輸出也是輸入頻率的1/N。


 


 因此我們得到結(jié)論一個最大計數(shù)長度為N(從0計數(shù)到N-1)的計數(shù)器,其最高位的輸出,是輸入頻率的N分頻


  通常 ASIC 和 FPGA 中,時鐘都是全局信號,都需要通過 PLL 處理才能使用,但某些簡易場合,采用計數(shù)器輸出時鐘也是能夠使用的,只是需要注意時序約束。


 


  (2)偶數(shù)倍分頻(占空比50%)


   偶數(shù)分頻,也就是2分頻、4分頻、6分頻...這個還是比較簡單的,N(N當(dāng)然是2的倍數(shù))分頻,那么計數(shù)到N/2-1,然后時鐘翻轉(zhuǎn)


 例如N=6時,代碼如下所示:



 1 module test#(parameter N=6)( 2 input clk, 3 input rst_n, 4 output clk_div 5 ); 6 reg div_reg ; 7 reg [N-1:0] div_cnt        ;//分頻計數(shù)器 8 always @(posedge clk or negedge rst_n) 9     if (rst_n == 1'b0 )begin10         div_cnt    <= 0 ;11         div_reg    <= 0 ;12     end 13     else if(div_cnt == (N/2 - 1))begin14         div_cnt    <= 0;15         div_reg    <= ~div_reg ;16     end 17     else18         div_cnt    <= div_cnt + 1'b1 ;19 20 assign clk_div = div_reg ;


仿真波形如下所示:


      


當(dāng)N=2的仿真波形如下所示:


        


 


 


 


  (3)奇數(shù)倍分頻


    ①占空比接近50%


   對于占空比不是50%的計數(shù)分頻,我們可以直接用上面的計數(shù)器方法,這里就不說了,我們介紹其他接近50%的占空比的方法,比如下面使用的狀態(tài)機(jī)分頻:


      


上圖的狀態(tài)機(jī)除了用一般的狀態(tài)機(jī)設(shè)計方式之外,我們也可以用簡單的計數(shù)器實現(xiàn),這種方法如下所示:


  假設(shè)時鐘分頻是N,則設(shè)置一個計數(shù)器,計數(shù)長度是N(即從0計數(shù)到N-1),然后在計數(shù)器為計數(shù)到(N-1)/2的時候,翻轉(zhuǎn)一下分頻時鐘信號;在計數(shù)器計數(shù)到為N-1的時候,再翻轉(zhuǎn)一下時鐘。


代碼如下所示:



 1 module test#(parameter N=3)(//N分頻,這里是3分頻 2 input clk, 3 input rst_n, 4 output clk_div 5 ); 6  7 reg [N-1:0] div_cnt        ;//分頻計數(shù)器 8 reg div_reg ; 9 always @(posedge clk or negedge rst_n)begin10     if (rst_n == 1'b0 )begin11         div_cnt    <= 0 ;12         div_reg        <= 1 ;13     end else if (div_cnt == (N-1)/2)begin//計數(shù)到(N-1)/2,進(jìn)行翻轉(zhuǎn)和繼續(xù)計數(shù)14         div_reg        <= ~div_reg;15         div_cnt    <= div_cnt + 1'b1 ;16     end else if ( div_cnt == (N-1) )begin//計數(shù)到N-1,進(jìn)行清零和翻轉(zhuǎn)17         div_cnt        <= 0 ;18         div_reg        <= ~div_reg;19     end else 20         div_cnt    <= div_cnt + 1'b1 ;21         22 end         23 assign clk_div = (N == 1)?clk:div_reg ;//注意這里24 25 26 endmodule


代碼中我們需要注意,在N= 1的情況,也就是不分頻的情況。仿真電路如下圖所示:


3分頻,N = 3:


      


5分頻,N= 5 :


         


 


不分頻,即N=1的仿真如下所示:


      


 


    ②占空比50%


      產(chǎn)生具有50%占空比的奇數(shù)分頻時鐘的算法如下所示,假設(shè)N分頻(N是計數(shù)):


  設(shè)置一個計數(shù)長度為N的上升沿計數(shù)器,和一個信號寄存器;信號寄存器在上升沿計數(shù)器為(N-1)/2的時候進(jìn)行翻轉(zhuǎn),然后再在計數(shù)到N-1的時候進(jìn)行翻轉(zhuǎn)(這里相當(dāng)于得到一個N分頻信號A)。


  再設(shè)置一個計數(shù)長度為N的下降沿計數(shù)器,和另一個信號寄存器;信號寄存器在下降沿計數(shù)器為(N-1)/2的時候進(jìn)行翻轉(zhuǎn),然后再在計數(shù)到N-1的時候進(jìn)行翻轉(zhuǎn)(這里相當(dāng)于得到一個N分頻信號B)。


  將A和B相或就可以得到占空比50%的奇數(shù)分頻信號;代碼實現(xiàn)如下:



 1 module test#(parameter N=5)(//N分頻 2 input clk, 3 input rst_n, 4 output clk_div 5 ); 6  7 reg sig_r ;//定義一個上升沿翻轉(zhuǎn)的信號 8 reg sig_f ;//定義一個下降沿翻轉(zhuǎn)的信號 9 reg [N-1:0]    cnt_r;//上升沿計數(shù)器10 reg [N-1:0]    cnt_f;//下降沿計數(shù)器11 12 wire clk_f ;13 assign clk_f = ~clk ;//用來觸發(fā)下降沿計數(shù)器的時鐘14                     //由于同時使用上升沿和下降沿觸發(fā)器不好,因此我們?yōu)橥贿呇?,都使用上升沿觸發(fā)15                     //只不過是將時鐘進(jìn)行反向16                     17 always @(posedge clk or negedge rst_n)begin//上升沿計數(shù)18     if(rst_n == 1'b0)begin19         sig_r    <= 0 ;20         cnt_r    <= 0 ;21     end else if( cnt_r == (N-1)/2 )begin22         sig_r    <= ~sig_r ;23         cnt_r    <= cnt_r + 1 ;24     end else if ( cnt_r == (N-1) )begin25         sig_r    <= ~sig_r ;26         cnt_r    <= 0 ;27     end else 28         cnt_r    <= cnt_r + 1 ;29 end                     30 31 always @(posedge clk_f or negedge rst_n)begin//下降沿計數(shù)32     if(rst_n == 1'b0)begin33         sig_f    <= 0 ;34         cnt_f    <= 0 ;35     end else if( cnt_f == (N-1)/2 )begin36         sig_f    <= ~sig_f ;37         cnt_f    <= cnt_f + 1 ;38     end else if ( cnt_f == (N-1) )begin39         sig_f    <= ~sig_f ;40         cnt_f    <= 0 ;41     end else 42         cnt_f    <= cnt_f + 1 ;43 end 44 45 assign clk_div = sig_f || sig_r ;46                     47 endmodule


 


仿真波形如下所示:


3分頻:


  


5分頻:


    


 


 


 


 ?。?)任意整數(shù)倍分頻(接近50%)


  在前面中,我們知道了一個最大計數(shù)長度為N(從0計數(shù)到N-1)的計數(shù)器,其最高位的輸出,是輸入頻率的N分頻,因此最簡單的任意分頻電路就是設(shè)計一個計數(shù)器,然后最高位輸出就是分頻的頻率了。雖然這這種方法很簡單,但是很顯然,這種方法的占空比是很糟糕的。因此我們要用其他的方法,也就是用其他的組合方式。


   ①占空比接近50%任意整數(shù)分頻


  這種方法是取自偶數(shù)分頻和奇數(shù)分頻里面的接近50%占空比,實現(xiàn)的代碼如下所示:



 1 module test #( parameter cfactor= 5)( 2   input clk, 3   input rst_n, 4   output clk_div 5 ); 6 reg clk_loc; 7 //reg [15:0] cnt;//allowed maximum clock division factor is 65536 8 reg [7:0] cnt;//allowed maximum clock division factor is 256 9 10 assign clk_div = (cfactor==1)? clk : clk_loc;11 //assign clk_div = ((rst==1) || (cfactor==1))? clk : clk_loc;12 13 always@(posedge clk or negedge rst_n)14   if(!rst_n)begin15     cnt <= 'd0;16     clk_loc = 1;17   end18   else begin19     cnt <= cnt + 1'b1;20     if(cnt==cfactor/2-1)21       clk_loc = 0;22     else if(cnt==cfactor-1) begin23       cnt <= 'd0;24       clk_loc = 1;25     end26   end27 28 endmodule


 


2分頻的仿真圖,如下所示:


    


5分頻的仿真波形如下所示:


    


 


 


    ②占空比50%的任意整數(shù)分頻(重點)


    這種方法是取自偶數(shù)分頻和奇數(shù)分頻都是50%占空比的組合,代碼如下所示:



 1 module test#(parameter N=1)(//N分頻 2 input clk, 3 input rst_n, 4 output clk_div 5 ); 6  7 //奇數(shù)分頻 8 reg sig_r ;//定義一個上升沿翻轉(zhuǎn)的信號 9 reg sig_f ;//定義一個下降沿翻轉(zhuǎn)的信號10 reg [N-1:0]    cnt_r;//上升沿計數(shù)器11 reg [N-1:0]    cnt_f;//下降沿計數(shù)器12 13 wire clk_f ;14 assign clk_f = ~clk ;//用來觸發(fā)下降沿計數(shù)器的時鐘15                     //由于同時使用上升沿和下降沿觸發(fā)器不好,因此我們?yōu)橥贿呇?,都使用上升沿觸發(fā)16                     //只不過是將時鐘進(jìn)行反向17                     18 always @(posedge clk or negedge rst_n)begin//上升沿計數(shù)19     if(rst_n == 1'b0)begin20         sig_r    <= 0 ;21         cnt_r    <= 0 ;22     end 23     else begin24         cnt_r    <= cnt_r + 1 ;25         if( cnt_r == (N-1)/2 )begin26             sig_r    <= ~sig_r ;27         end else if ( cnt_r == (N-1) )begin28             sig_r    <= ~sig_r ;29             cnt_r    <= 0 ;30         end 31     end 32 end                     33 34 always @(posedge clk_f or negedge rst_n)begin//下降沿計數(shù)35     if(rst_n == 1'b0)begin36         sig_f    <= 0 ;37         cnt_f    <= 0 ;38     end 39     else begin40         cnt_f    <= cnt_f + 1 ;41         if( cnt_f == (N-1)/2 )begin42             sig_f    <= ~sig_f ;43         end else if ( cnt_f == (N-1) )begin44             sig_f    <= ~sig_f ;45             cnt_f    <= 0 ;46         end 47     end     48 end 49 50 //偶數(shù)分頻51 reg div_reg ;52 reg [N-1:0] div_cnt        ;//分頻計數(shù)器53 always @(posedge clk or negedge rst_n)begin54     if (rst_n == 1'b0 )begin55         div_cnt    <= 0 ;56         div_reg    <= 0 ;57     end 58     else begin59         div_cnt    <= div_cnt + 1'b1 ;60         if(div_cnt == (N/2 - 1))begin61             div_cnt    <= 0;62             div_reg    <= ~div_reg ;63         end 64     end65 end        66 assign clk_div = (N == 1)?clk:67                 ( N%2 == 1)?(sig_f || sig_r ): div_reg;//這里用來輸出分頻值。對2的取余操作是綜合的68                     69 endmodule 


 


仿真波形如下所示:


5分頻:


    


6分頻:


      


 


   


 總結(jié):本文介紹了計數(shù)器及其功能,主要是介紹了作為分頻器的功能。對于分頻器,如下所示:


          


 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
基于FPGA的任意分頻器設(shè)計
關(guān)于分頻器的FPGA實現(xiàn)整理思路
淺談FPGA學(xué)習(xí)之奇葩分頻體驗
用verilog語言寫的任意整數(shù)的分頻器
FPGA
Verilog 及Xilinx_FPGA入門(一)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服