FPGA中用verilog分頻實現方法

 
分頻器是FPGA設計中使用頻率非常高的基本設計之一,儘管在目前大部分設計中,廣泛使用芯片廠家集成的鎖相環資源,如altera 的PLL,Xilinx的DLL.來進行時鐘的分頻,倍頻以及相移。但是對於時鐘要求不高的基本設計,通過語言進行時鐘的分頻相移仍然非常流行,首先這種方法可以節省芯片內部的鎖相環資源,再者,消耗不多的邏輯單元就可以達到對時鐘操作的目的。另一方面,通過語言設計進行時鐘分頻,可以看出設計者對設計語言的理解程度。
 

           第一,偶數倍分頻:偶數倍分頻應該是大家都比較熟悉的分頻,通過計數器計數是完全可以實現的。如進行N倍偶數分頻,那麼可以通過由待分頻的時鐘觸發計數器計數,當計數器從0計數到N/2‐1時,輸出時鐘進行翻轉,並給計數器一個復位信號,使得下一個時鐘從零開始計數。以此循環下去。這種方法可以實現任意的偶數分頻。

            第二:奇數倍分頻:奇數倍分頻常常在論壇上有人問起,實際上,奇數倍分頻有兩種實現方法:
                          首先,完全可以通過計數器來實現,如進行三分頻,通過待分頻時鐘上升沿觸發計數器進行模三計數,當計數器計數到鄰近值進行兩次翻轉,比如可以在計數器計數到1時,輸出時鐘進行翻轉,計數到2時再次進行翻轉。即是在計數值在鄰近的1和2進行了兩次翻轉。這樣實現的三分頻佔空比爲1/3或者2/3。 
         always@(posedge gclk)                   always@(negedge gclk)                  
             if(count==1||count==2)                if(count==1||count==2)
                       begin                                       begin
                          clk1 =~clk1;                             clk2=~clk2;
                          count=count%3;                     count=count%3;
                       end                                       end
                                 assign jclk =clk1||clk2;    
                 
                       
               如果要實現佔空比爲50%的三分頻時鐘,可以通過待分頻時鐘下降沿觸發計數,和上升沿同樣的方法計數進行三分頻,然後下降沿產生的三分頻時鐘和上升沿產生的時鐘進行相或運算,即可得到佔空比爲50%的三分頻時鐘。這種方法可以實現任意的奇數分頻。歸類爲一般的方法爲:對於實現佔空比爲50%的N倍奇數分頻,首先進行上升沿觸發進行模N計數,計數選定到某一個值進行輸出時鐘翻轉,然後經過(N‐1)/2再次進行翻轉得到一個佔空比非50%奇數n分頻時鐘。再者同時進行下降沿觸發的模N計數,到和上升沿觸發輸出時鐘翻轉選定值相同值時,進行輸出時鐘時鐘翻轉,同樣經過(N‐1)/2時,輸出時鐘再次翻轉生成佔空比非50%的奇數n分頻時鐘。兩個佔空比非50%的n分頻時鐘相或運算,得到佔空比爲50%的奇數n分頻時鐘。               另外一種方法:對進行奇數倍n分頻時鐘,首先進行n/2分頻(帶小數,即等於(n‐1)/2+0.5),然後再進行二分頻得到。得到佔空比爲50%的奇數倍分頻。(採用非沿觸發,爲什麼不用呢?)

           第三 ,小數分頻:首先講講如何進行n+0.5分頻,這種分頻需要對輸入時鐘進行操作。基本的設計思想:對於進行n+0.5分頻,首先進行模n的計數,在計數到n‐1時,輸出時鐘賦爲'1’,回到計數0時,又賦爲0,因此,可以知道,當計數值爲n‐1時,輸出時鐘才爲1,因此,只要保持計數值n‐1爲半個輸入時鐘週期,即實現了n+0.5分頻時鐘,因此保持n‐1爲半個時鐘週期即是一個難點。從中可以發現,因爲計數器是通過時鐘上升沿計數,因此可以在計數爲n‐1時對計數觸發時鐘進行翻轉,那麼時鐘的下降沿變成了上升沿。即在計數值爲n‐1期間的時鐘下降沿變成了上升沿,則計數值n‐1只保持了半個時鐘週期,由於時鐘翻轉下降沿變成上升沿,因此計數值變爲0。因此,每產生一個n+0.5分頻時鐘的週期,觸發時鐘都是要翻轉一次.
 
      

module three (clk,d,out);
input clk;
output d,out;
reg q1,q2,d,out;

initial
     begin
              d= 0;//   d是1.5倍分頻的輸出;
             out = 0;
      end//必須進行初始化;
 
always@(posedge clk)
         if (!d)
             q1 = 1'b1;
             else
             q1 =~q1;
  
   always@(negedge clk)
       if(!d)
                q2 = 1'b1;
        else
                 q2 =~ q2;
   always@(q1 or q2)
          d = q1 & q2;


   always@(posedge d)
    out =~ out;//3倍分頻輸出
   

    endmodule


 

 
 
 
 
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章