前言
FPGA開發(fā)板上一般只有一個晶振,即一種時鐘頻率。數(shù)字系統(tǒng)設計中,時間的計算都要以時鐘作為基本單元,對基準時鐘進行不同倍數(shù)的分頻而得到各模塊所需時鐘頻率,可通過Verilog代碼實現(xiàn);倍頻可通過鎖相環(huán)【PLL】實現(xiàn)。
分頻原理
把輸入信號的頻率變成成倍的低于輸入頻率的輸出信號;每經(jīng)歷幾個單位時鐘周期就輸出一個時鐘周期。
例:clk_in
為12MHz;clk_out
為2MHz.則分頻系數(shù)為6
。那么如何實現(xiàn)6
分頻:
??把輸入信號作為計數(shù)脈沖(邊沿觸發(fā)一次,計數(shù)一次),
當計數(shù)6次,為輸出信號的一個周期,此時輸入信號經(jīng)歷了6個周期,置0,重新開始計數(shù),循環(huán)往復。(前提:輸入信號占空比50%)
而輸出信號的不同占空比的實現(xiàn)無非是輸出信號經(jīng)歷的單位周期輸出高低電平不同;
偶數(shù)分頻
?? 6分頻
占空比50%:6分頻電路:一個
always
塊實現(xiàn)一個模3計數(shù)器。
???? 另一個always
塊實現(xiàn)當計數(shù)到2(從0計數(shù)到2,計數(shù),3次)輸出信號翻轉,
???? 占空比50%。
占空比不是50%:先實現(xiàn)模6計數(shù)器,然后可任意設計當計數(shù)到某個值輸出高電平,再計數(shù)到另一個值輸出低電平。
?? 代碼
//不帶標志位占空比50%
module divider_six(clk,reset,clk_out,cnt);
input clk;
input reset;
output reg clk_out;
output reg [1:0] cnt;//用于計數(shù)的寄存器; always塊內(nèi),reg型變量
always@(posedge clk)
if(reset == 1'b0)
cnt <= 2'd0;
else if(cnt == 2'd2)//從0開始,計數(shù)到2,計數(shù)為3,則6分頻
cnt <= 2'd0;
else
cnt <= cnt + 1'b1;
//計數(shù)3次,輸出翻轉;所以cnt計數(shù)3次作為標志,實現(xiàn)翻轉功能
always@(posedge clk)
if(reset == 1'b0)
clk_out <= 1'b0;
else if(cnt == 2'd2)
clk_out <= ~clk_out;
else;
endmodule
?? tb
`timescale 1ns/100ps
`define clk_cycle 50
module divider_six_tb;
reg clk;
reg reset;
wire clk_out;
wire [1:0]cnt;
always #(`clk_cycle) clk = ~clk;//產(chǎn)生測試時鐘,時鐘周期100ns(s>ms>us>ns>ps)
initial begin
clk = 0;
reset = 1;
#10 reset = 0;
#110 reset = 1;
#100000
$stop;
end
divider_six u1(
.reset(reset),
.clk(clk),
.clk_out(clk_out),
.cnt(cnt)
);
endmodule
?? 仿真波形
奇數(shù)分頻
算法
:需要在系統(tǒng)時鐘為上升沿和下降沿都工作(不是同時工作)
? ? 產(chǎn)生50%的占空比,需要設計兩個分頻時鐘跳變點,分頻周期的N-1
和(N-1)/2
。
例:13分頻
:兩個分頻時鐘跳變點:6[(13-1)/2]和12[13-1],此時輸出保持7個高電平時鐘周期,6個低電平時鐘周期分別在上升沿觸發(fā)clk1
和下降沿觸發(fā)clk2
,兩者相位相差半個單位周期,clk_out = clk1 & clk2;
之后clk_out
占空比50%
如圖仿真波形:
??仿真波形
??代碼
//13分頻,占空比為50%
module div_13(clk,reset,clk_out,clk1,clk2);
input clk;
input reset;
output clk_out;
reg [3:0] cnt;
output reg clk1;
output reg clk2;
//計數(shù)從0到12
always@(posedge clk)
if(reset == 1'b0 || cnt == 4'd12)
cnt <= 4'd0;
else
cnt <= cnt + 1'b1;
//實現(xiàn)分頻,clk1:7個高電平時鐘周期,6個低電平時鐘周期,上升沿觸發(fā)
always@(posedge clk)
if(reset == 1'b0)
clk1 <= 1'b0;
else if(cnt == 4'd6)//復位后,計數(shù)到6,開始低電平,保持6個周期,
clk1 <= 1'b0; //此時計數(shù)到12,重新計數(shù),保持高電平直至計數(shù)到6
else if(cnt == 4'd12)//計數(shù)到6和12,這兩個是分頻跳變點
clk1 <= 1'b1; //如何得到?N-1;(N-1)/2
//clk2:下降沿觸發(fā),7個高電平時鐘周期,6個低電平時鐘周期
always@(negedge clk)
if(reset == 1'b0)
clk2 <= 1'b0;
else if(cnt == 4'd6)
clk2 <= 1'b0;
else if(cnt == 4'd12)
clk2 <= 1'b1;
//clk1,clk2兩者相差半個時鐘周期
//clk1,clk2配合作用,都計數(shù)7次后,clk1立即回到低電平,而clk2延遲半個周期
assign clk_out = clk1 & clk2;
endmodule
??tb
`timescale 1ns/100ps
`define clk_cycle 50
module div_13_tb;
reg clk;
reg reset;
wire clk_out;
wire clk1;
wire clk2;
always #(`clk_cycle) clk = ~clk;//產(chǎn)生測試時鐘,時鐘周期100ns(s>ms>us>ns>ps)
initial begin
clk = 0;
reset = 1;
#10 reset = 0;
#110 reset = 1;
#100000
$stop;
end
div_13 u1(
.reset(reset),
.clk(clk),
.clk_out(clk_out),
.clk1(clk1),
.clk2(clk2)
);
endmodule
小數(shù)分頻
?? 說明
1.等效意義上的小數(shù)分頻:例5.3分頻,沒有周期為5.3的分頻電路,實際是輸出時鐘53的周期對應于輸出時鐘的10個周期。
2.按序輸出:時鐘用處不大,沒有意義
3.插入亂序輸出:防止相位抖動,把多出來的脈沖均勻分散開
?半整數(shù)分頻:N+0.5
思路
:例:5.5分頻
原時鐘的半周期為單位,此時周期為11可分頻輸出6高5低。
上升沿觸發(fā),使得clk1
前6周期輸出高電平【N-1=10為一個跳變點】后5周期輸出低電平【N-1)/2=5為另一個跳變點】;
下降沿觸發(fā)使得clk2
前5周期為低電平(cnt為0時的跳變點),后6【cnt=N-1)/2=5】周期為高電平。兩個信號相與即為分頻信號clk_div = clk1 & clk2;
,類似奇分頻
??仿真波形
??代碼
//5.5分頻
//原時鐘周期一半為單位,輸出1高10低,從0到10計數(shù),前6周期高電平,后5周期低電平;
//再使用下降沿觸發(fā)前5周期低電平,前6周期高電平,最后相與
module div_half_1(clk,rst_n,clk_div,clk1,clk2,cnt);
input clk;
input rst_n;
output clk_div;
output reg[3:0] cnt;
output reg clk1;
output reg clk2;
//從0到10計數(shù) 模11
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 4'd0;
else if (cnt==4'd10)
cnt <= 0;
else
cnt <= cnt + 1'b1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
clk1 <= 1'b0;
else if(cnt==4'd10)//6個周期的高電平N-1=10
clk1 <= 1'b1;
else if(cnt==4'd5)//5個周期的低電平(N-1)/2=5
clk1 <= 1'b0; //兩個跳變點,(N-1)/2;N-1
//clk2相比于clk1延時半個時鐘周期,
always@(negedge clk or negedge rst_n)
if(!rst_n)
clk2 <= 1'b0;
else if(cnt==4'd0)//5個周期的低電平
clk2 <= 1'b0;
else if(cnt==4'd5)//6個周期的高電平
clk2 <= 1'b1;
assign clk_div = clk1 & clk2;
endmodule
??tb
`timescale 1ns/100ps
`define clk_cycle 50
module div_half_1_tb;
reg clk;
reg reset;
wire clk_out;
wire clk1;
wire clk2;
wire[3:0] cnt;
always #(`clk_cycle) clk = ~clk;//產(chǎn)生測試時鐘,時鐘周期100ns(s>ms>us>ns>ps)
initial begin
clk = 0;
reset = 1;
#10 reset = 0;
#110 reset = 1;
#100000
$stop;
end
div_half_1 u1(
.rst_n(reset),
.clk(clk),
.clk_div(clk_out),
.clk1(clk1),
.clk2(clk2),
.cnt(cnt)
);
endmodule
?小數(shù)分頻
?? 5.3分頻
53/10=5.3 設5分頻a次;6分頻次
a+b=10;
5a+6b=53 ->a=7 ; b=3
如何插入排序:6556556555
Verilog實現(xiàn):
脈沖刪除:53個單位周期刪除43個算法
:分母作為累加值,在clk
的上升沿cnt
加上分母10,判斷是否大于分子,若小于(脈沖刪除標志為1,刪除)繼續(xù)累加,若大于(脈沖刪除標志為0,不刪除)在下一周期減去分子。結果剛好是6556556555(由來:分母-余數(shù)=7,作為累加值,大于分母,輸出N分頻,然后減去分母,繼續(xù)累加7,;小于分母,輸出N+1分頻)
??代碼
//脈沖刪除小數(shù)分頻
module div_5_3_1(clk,rst_n,clk_out,cnt);
input clk;
input rst_n;
output clk_out;
parameter fra = 6'd53;//分子
parameter den = 6'd10;//分母
output reg[5:0] cnt;
reg flag_del;//脈沖刪除標志位
always@(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt <= 6'd0;
flag_del <= 1'b0;
end
//大于分子,不刪除
else if(cnt>fra) begin
cnt <= cnt + den - fra;
flag_del <= 1'b0;
end
//小于分子,累加;刪除:保持高電平
else begin
cnt <= cnt + den;
flag_del <= 1'b1;
end
end
assign clk_out = flag_del ? 1 : clk;
endmodule
??tb
`timescale 1ns/100ps
`define clk_cycle 50
module div_5_3_1_tb;
reg clk;
reg reset;
wire clk_out;
wire [5:0]cnt;
always #(`clk_cycle) clk = ~clk;//產(chǎn)生測試時鐘,時鐘周期100ns(s>ms>us>ns>ps)
initial begin
clk = 0;
reset = 0;
#10 reset = 0;
#110 reset = 1;
#100000
$stop;
end
div_5_3_1 u1 (
.clk(clk),
.rst_n(reset),
.clk_out(clk_out),
.cnt(cnt)
);
endmodule
??仿真波形
最后
不足之處:未實現(xiàn)參數(shù)化編程;
參考:文章來源:http://www.zghlxwxcb.cn/news/detail-430275.html
https://blog.csdn.net/weixin_43698385/article/details/122773225
https://blog.csdn.net/Reborn_Lee/article/details/97553078
https://blog.csdn.net/wangyanchao151/article/details/81204126?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%B0%8F%E6%95%B0%E5%88%86%E9%A2%91&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-5-81204126.nonecase&spm=1018.2226.3001.4187文章來源地址http://www.zghlxwxcb.cn/news/detail-430275.html
到了這里,關于FPGA基礎設計(二):任意分頻器(奇數(shù),偶數(shù),小數(shù))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!