備忘_數字IC_verilog_分頻
1.偶數
要實作一個N分頻(N為偶數)的分頻器,可以先寫一個計數器,當計數到(N/2-1)時,讓輸出狀态翻轉,并将計數器清零,這樣輸出的信号就是輸入時鐘的N分頻
偶數分頻器示例,20分頻即N=20,占空比50%
module clk_div(
clk,
rst,
div,
clk_out
);
input clk; //50MHZ
input rst;
input div; //divide number ,int
output clk_out;
reg clk_out = 1'b0;
reg [31:0] cnt;
wire [31:0] div;
always @(posedge clk) begin
if (rst) begin
cnt <= 32'b0;
clk_out <= 1'b0;
end
else if (cnt == ((div/2) - 32'd1)) begin
clk_out <= ~clk_out;
cnt <= 32'b0;
end
else begin
cnt <= cnt + 1'b1;
end
end
endmodule
2.奇數
如果對占空比沒有明确的要求,則可以直接對上升沿計數,計數到(N-1)/2 時讓輸出翻轉,計數到(N-1)時讓輸出狀态再次翻轉,并将計數器清零,這樣就可以得到一個占空比為2:3的N分頻(N為奇數)的分頻器。而如果要實作50%的占空比,可以通過“錯位相或”的方法實作。具體方法是用剛才的方法先通過對上升沿計數産生一個占空比為不是50%的N分頻器,再用同樣的方法對下降沿計數産生一個占空比也不是50%的N分頻器,最後将這兩個分頻器的輸出進行“或”運算,就可以得到占空比為50%的奇數N分頻器
奇數分頻器示例,5分頻,占空比50%
module clk_div1(
clk,
rst,
div,
clk_p,
clk_n,
clk_out
);
input clk,rst,div;
output clk_out,clk_p,clk_n;
//wire clk_out = 1’b0;
reg clk_p = 1’b0;
reg clk_n = 1’b0;
reg [31:0]cnt_p = 32’d0;
reg [31:0]cnt_n = 32’d0;
wire [31:0] div;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_p <= 32’b0;
clk_p <= 1’b0;
end
else if (cnt_p == ((div-1’b1)/2)) begin
clk_p <= ~clk_p;
cnt_p <= cnt_p + 32’d1;
end
else if (cnt_p == (div-1’b1)) begin
clk_p <= ~clk_p;
cnt_p <= 1’b0;
end
else cnt_p <= cnt_p + 32’d1;
end
always @(negedge clk or posedge rst) begin
if (rst) begin
cnt_n <= 32’b0;
clk_n <= 1’b0;
end
else if (cnt_n == ((div-1’b1)/2)) begin
clk_n <= ~clk_n;
cnt_n <= cnt_n + 32’d1;
end
else if (cnt_n == (div-1’b1)) begin
clk_n <= ~clk_n;
cnt_n <= 1’b0;
end
else cnt_n <= cnt_n + 32’d1;
end
assign clk_out = clk_p | clk_n;
endmodule
3.任意分頻——基于相位累加原理
相位累加器主要用在直接數字頻率合成器(DDS)中,其中的幾個主要的參數為輸入頻率fc,輸出頻率fo,計數器位寬N,頻率控制字K(即計數器遞增步長)。它們之間的關系為:fo=(fcK)/(2N)。假設輸入頻率fc為50MHz,計數器位寬N為32,要産生1kHz的信号,則K=(fo*2N)/fc=85.9fo=85900。當計數值小于等于((2N)/2)時,輸出低電平,當計數值大于((2N)/2)時,輸出高電平,依次循環,就可以産生占空比為50%的1kHz信号
任意分頻示例,輸出1kHz,占空比50%
module div_free(clk_out, clk, rst_n);
input clk, rst_n;
output clk_out;
reg clk_out;
reg [31:0] cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 0;
else cnt <= cnt + 32’d85900; //計數器步長 K
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
clk_out <= 1’b0;
end
else if(cnt < 32’h7FFF_FFFF)
clk_out <= 1’b0;
else clk_out <= 1’b1;
endmodule
4.小數/分數 分頻
脈沖删除小數分頻
小數均可以化為分數
以13/4分頻為例,我們首先要想明白什麼是13/4分頻。什麼是2分頻呢?就是每兩個輸入時鐘得到一個輸出時鐘,4分頻就是4/1即四個輸入時鐘得到一個輸出時鐘,是以13/4分頻其實就是13個輸入時鐘得到4個輸出時鐘,想明白這一點很重要。
13/4分頻其實就是13個輸入時鐘得到4個輸出時鐘,是以脈沖删除小數分頻相對比較簡單。意思就是在13個輸入時鐘裡我删掉9個時鐘周期,這樣就輸出了4個時鐘周期了
1.設定寄存器cnt位寬自定,我用的[7:0],初始值為0;
2.在clk_in的上升沿+4,并判斷是否大于13,若大于13在下一周期-13;
3.cnt小于13時候,删除脈沖信号delete=1,大于13時候delete=0;
module clk_divfloat(
clk,
rst,
clk_out
);
parameter fenzi = 13;
parameter fenmu = 4;
input clk,rst;
output clk_out;
reg [31:0] cnt = 32’d0;
reg delete = 1’b0;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt <= 32’d0;
delete <= 1’b0;
end
else if (cnt > fenzi) begin
cnt <= cnt + fenmu - fenzi;
delete <= 1’b0;
end
else begin
cnt <= cnt + fenmu;
delete <= 1’b1;
end
end
assign clk_out = delete ? 1’b1 : clk;
endmodule