基於verilog的分頻器設計(奇偶分頻原理及其電路實現:上)


在一個數字系統中往往需要多種頻率的時鍾脈沖作為驅動源,這樣就需要對FPGA的系統時鍾(頻率太高)進行分頻。分頻器主要分為奇數分頻,偶數分頻,半整數分頻和小數分頻,在對時鍾要求不是很嚴格的FPGA系統中,分頻器通常都是通過計數器的循環來實現的。

偶數分頻:假設為N分頻,由待分頻的時鍾觸發計數器計數,當計數器從0計數到N/2-1時,輸出時鍾進行翻轉,並給計數器一個復位信號,使得下一個時鍾從零開始計數。以此循環下去。這種方法可以實現任意的偶數分頻。如圖所示,兩個D觸發器級聯實現四分頻電路,原理:來一個時鍾脈沖,D端數據就被送到輸出端Q,同時輸出一個反向數據到Q非端,下一個時鍾脈沖到,重復上面過程,但數據己被取反,由此每兩個時鍾,Q端數被取反一次,由此得到二份頻,繼而得到四分頻。

image_thumb1

Tips: D觸發器的工作原理(驗證其狀態不變,可先假定初值為0或為1,根據邏輯關系分析)

image_thumb3

D觸發器的狀態表:CP為時鍾,R為置零端,S為置1端,D為信號輸入端,輸出信號有Q。

image

實現D觸發器功能的verilog代碼為

module D(q,qn,d,cp,r,s);
output q,qn; //D  觸發器的兩個輸出
input d,cp,r,s; //D  觸發器的四個輸入
reg q,qn; // 輸出寄存器
always@(posedge cp)  //在 在 cp  的上升沿觸發
begin
if({r,s}==2'b01) // 判斷是否有 r=0,s=1
begin
q=1'b0;
qn=1'b1;
end
else if({r,s}==2'b10) // 判斷是否有 r=1,s=0
begin
q=1'b1;
qn=1'b0;
end
else if({r,s}==2'b11) // 判斷是否有 r=1 ,s=1
begin
q=d;
qn=~d;
end
end
endmodule

對於分頻系數為10的分頻器,本例的輸入時鍾系統50M時鍾(clk_50M),輸出為十分頻時鍾(f_50)。設置一個3位的計數器,當計時寄存器到4(10/2-1)時,將輸出分頻信號取反即可得到10分頻的輸出。下圖分別為功能仿真時序仿真(存在延遲)

module fengping_2(clk_50M,f_10);
input clk_50M; // 系統輸入時鍾,50M ,周期 20ns
output f_10;  //10  分頻輸出,5M
reg f_10;  // 輸出寄存器
reg[2:0] cnt;  // 計數寄存器
always@(posedge clk_50M) // 每個時鍾周期的上升沿觸發,
// 執行 begin_end  中的語句
begin
if(cnt==3'b100)  // 判斷 cnt  是否為 4, 是的話執行以下程序
begin
f_10<=~f_10; //把 把 f_10  取反
cnt<=3'b0;  // 計數寄存器清零
end
else //cnt  沒到 4 ,執行以下程序
begin
cnt<=cnt+3'b1;// 計數寄存器自加一
end
end
endmodule

image

image

奇數分頻:首先,完全可以通過計數器來實現,如進行三分頻,通過待分頻時鍾上升沿觸發計數器進行模三計數,當計數器計數到鄰近值進行兩次翻轉,比如可以在計數器計數到1時,輸出時鍾進行翻轉,計數到2時再次進行翻轉。即是在計數值在鄰近的1和2進行了兩次翻轉。這樣實現的三分頻占空比為1/3或者2/3。如果要實現占空比為50%的三分頻時鍾,可以通過待分頻時鍾下降沿觸發計數,和上升沿同樣的方法計數進行三分頻,然后下降沿產生的三分頻時鍾和上升沿產生的時鍾進行相或運算,即可得到占空比為50%的三分頻時鍾。這種方法可以實現任意的奇數分頻。歸類為一般的方法為:對於實現占空比為50%的N倍奇數分頻,首先進行上升沿觸發進行模N計數,計數選定到某一個值進行輸出時鍾翻轉,然后經過(N-1)/2再次進行翻轉得到一個占空比非50%奇數n分頻時鍾。再者同時進行下降沿觸發的模N計數,到和上升沿觸發輸出時鍾翻轉選定值相同值時,進行輸出時鍾時鍾翻轉,同樣經過(N-1)/2時,輸出時鍾再次翻轉生成占空比非50%的奇數n分頻時鍾。兩個占空比非50%的n分頻時鍾相或運算,得到占空比為50%的奇數n分頻時鍾。

module fenpin(
  input  i_clk,
  input  i_rst_n,
   
  output o_clk
);
  
// log2(3) = 1.5850 <= 2  
reg [1:0] cnt_p;                        // 上升沿計數子
  
// 3位上升沿計數器: 0 ~ 2
always @ (posedge i_clk, negedge i_rst_n)
begin
  if (!i_rst_n)
    cnt_p <= 0;
  else
    begin
    if (cnt_p == 2)            //2=3-1
      cnt_p <= 0;
    else
      cnt_p <= cnt_p + 1'b1;
    end
end
 
// log2(3) = 1.5850 <= 2  
reg [1:0] cnt_n;                        // 下降沿計數子
 
// 3位下降沿計數器: 0 ~ 2
// 2 = 3 - 1
always @ (negedge i_clk, negedge i_rst_n)
begin
  if (!i_rst_n)
    cnt_n <= 0;
  else
  begin
    if (cnt_n == 2)                  //2=3-1
      cnt_n <= 0;
    else
      cnt_n <= cnt_n + 1'b1;
  end
end
  
 
reg o_clk_p;                            // 上升沿時鍾輸出寄存器
 
// 輸出上升沿時鍾
// 0     ~ 1 ↑-> 1
// (1+1) ~ 2 ↑-> 0
// 1 = 3>>1
// 2 = 3 - 1
always @ (posedge i_clk, negedge i_rst_n)
begin
  if (!i_rst_n)
    o_clk_p <= 0;
  else
  begin
    if (cnt_p <= 1)                     // 1 = 3>>1 ,右移相當於除以2
      o_clk_p <= 1;
    else
      o_clk_p <= 0;
  end
end
  
reg o_clk_n;                            // 下降沿時鍾輸出寄存器
 
// 輸出下降沿時鍾
// 0     ~  1 ↓-> 1
// (1+1) ~  2 ↓-> 0
// 1 = 3>>1
// 2 = 3 - 1
always @ (negedge i_clk, negedge i_rst_n)
begin
  if (!i_rst_n)
    o_clk_n <= 0;
  else
  begin
    if (cnt_n <= 1)                     // 1 = 3>>1 
      o_clk_n <= 1;
    else
      o_clk_n <= 0;
  end
end
 
assign o_clk = o_clk_n & o_clk_p;       // 按位與(作用:掩碼)
  
endmodule

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM