- 一、前言
-
二、偶數(shù)分頻
- 2.1 觸發(fā)器級(jí)聯(lián)法
- 2.2 計(jì)數(shù)器法
- 2.3 verilog代碼
- 2.4 Testbench
- 2.5 仿真結(jié)果
-
三、奇數(shù)分頻
- 3.1 占空比非50%奇數(shù)分頻
- 3.2 占空比50%奇數(shù)分頻
- 3.3 Verilog代碼
- 3.4 Testbench
- 3.5 仿真結(jié)果
-
四、小數(shù)分頻
- 4.1 雙模前置分頻法
- 4.2 Verilog代碼
- 4.3 Testbench
- 4.4 仿真結(jié)果
-
五、半整數(shù)分頻
- 5.1 占空比50%半整數(shù)分頻
- 5.2 Verilog代碼
- 5.3 Testbench
- 5.4仿真結(jié)果
-
六、狀態(tài)機(jī)分頻
- 6.1狀態(tài)機(jī)分頻
- 6.2 verilog代碼
- 6.3 Tsetbench
- 6.4仿真結(jié)果
- 七、總結(jié)
數(shù)字IC經(jīng)典電路設(shè)計(jì)
經(jīng)典電路設(shè)計(jì)是數(shù)字IC設(shè)計(jì)里基礎(chǔ)中的基礎(chǔ),蓋大房子的第一部是打造結(jié)實(shí)可靠的地基,每一篇筆者都會(huì)分門別類給出設(shè)計(jì)原理、設(shè)計(jì)方法、verilog代碼、Testbench、仿真波形。然而實(shí)際的數(shù)字IC設(shè)計(jì)過程中考慮的問題遠(yuǎn)多于此,通過本系列希望大家對(duì)數(shù)字IC中一些經(jīng)典電路的設(shè)計(jì)有初步入門了解。能力有限,紕漏難免,歡迎大家交流指正。
快速導(dǎo)航鏈接如下:
個(gè)人主頁(yè)鏈接
1.數(shù)字分頻器設(shè)計(jì)
2.序列檢測(cè)器設(shè)計(jì)
3.序列發(fā)生器設(shè)計(jì)
4.序列模三檢測(cè)器設(shè)計(jì)
5.奇偶校驗(yàn)器設(shè)計(jì)
6.自然二進(jìn)制數(shù)與格雷碼轉(zhuǎn)換
一、前言
作為IC設(shè)計(jì)中經(jīng)典電路之一,數(shù)字分頻器在IC(集成電路)設(shè)計(jì)中有廣泛的應(yīng)用。以下是數(shù)字分頻器在IC設(shè)計(jì)中的一些應(yīng)用:
時(shí)鐘發(fā)生器:時(shí)鐘發(fā)生器的原理是時(shí)鐘分頻,數(shù)字分頻器可以用來將時(shí)鐘信號(hào)分頻為所需的頻率。例如,如果需要一個(gè)1Hz的時(shí)鐘信號(hào),可以使用數(shù)字分頻器將10Hz的時(shí)鐘信號(hào)分頻為1Hz,滿足模塊時(shí)序要求外還可以達(dá)到降低功耗的作用。時(shí)鐘發(fā)生器是數(shù)字系統(tǒng)中非常重要的組件,你就說重不重要!
數(shù)字鎖相環(huán)(DLL):數(shù)字分頻器可以用于數(shù)字鎖相環(huán)的設(shè)計(jì)中,以實(shí)現(xiàn)時(shí)鐘的相位同步。在 IC 設(shè)計(jì)中,時(shí)鐘同步是非常重要的一部分,因?yàn)闀r(shí)鐘信號(hào)的穩(wěn)定性和精度直接影響到整個(gè)系統(tǒng)的性能和可靠性。數(shù)字鎖相環(huán)是數(shù)字系統(tǒng)中的一種重要的時(shí)鐘同步技術(shù)之一。你就說重不重要!
數(shù)字頻率合成器(DDS):數(shù)字分頻器可以用于數(shù)字頻率合成器的設(shè)計(jì)中,以產(chǎn)生所需的頻率。在頻率合成器中,數(shù)字分頻器可以用于將高頻信號(hào)分頻為多個(gè)低頻信號(hào),然后通過DSP進(jìn)行數(shù)字信號(hào)處理和合成,最終生成一個(gè)高頻信號(hào)。雖然分頻只能將高頻分解成低頻信號(hào),但是與DSP結(jié)合可以合成高頻信號(hào)??煞纸飧哳l信號(hào)亦可合成高頻信號(hào),你就說重不重要!
總之,數(shù)字分頻器在IC設(shè)計(jì)中有廣泛的應(yīng)用。它是數(shù)字系統(tǒng)中重要的組件之一,可以實(shí)現(xiàn)各種復(fù)雜的數(shù)字信號(hào)處理和時(shí)鐘同步技術(shù)。它是現(xiàn)代電子技術(shù)中不可或缺的一部分。所以掌握數(shù)字分頻器的設(shè)計(jì)是十分重要的!
二、偶數(shù)分頻
2.1 觸發(fā)器級(jí)聯(lián)法
采用觸發(fā)器反向輸出端連接到輸入端的方式,寄存器級(jí)聯(lián)法能實(shí)現(xiàn)2^N的偶數(shù)分頻,具體是采用寄存器結(jié)構(gòu)的電路,每當(dāng)時(shí)鐘上升沿到來的時(shí)候輸出結(jié)果進(jìn)行翻轉(zhuǎn),以此來實(shí)現(xiàn)偶數(shù)分頻。
根據(jù)以上原理,可實(shí)現(xiàn)簡(jiǎn)單的 2 分頻電路,以此為基礎(chǔ)進(jìn)行串聯(lián),可構(gòu)成 4 分頻和8 分頻電路。電路結(jié)構(gòu)如下圖所示,用 Verilog 描述時(shí)只需使用簡(jiǎn)單的取反邏輯即可。
在此基礎(chǔ)上可畫出2分頻、4分頻、8分頻電路的波形圖(圖由TimeGen繪制,該軟件功能實(shí)用,推薦使用),如下圖所示。
2分頻設(shè)計(jì):只需要使用基準(zhǔn)時(shí)鐘在第1個(gè)時(shí)鐘周期輸出高電平(或低電平),在第2個(gè)時(shí)鐘周期輸出相反電平。
同理,4分頻設(shè)計(jì):使用基準(zhǔn)時(shí)鐘在第1、2個(gè)時(shí)鐘周期輸出高電平(或低電平),在第3、4個(gè)時(shí)鐘周期輸出相反電平。
同理,8分頻設(shè)計(jì):使用基準(zhǔn)時(shí)鐘在第1、2、3、4個(gè)時(shí)鐘周期輸出高電平(或低電平),在第5、6、7、8個(gè)時(shí)鐘周期輸出相反電平。
2.2 計(jì)數(shù)器法
如果偶數(shù)分頻系數(shù)過大或者寄存器級(jí)聯(lián)法無法實(shí)現(xiàn)對(duì)應(yīng)的分頻,可以采用計(jì)數(shù)器法進(jìn)行分頻,計(jì)數(shù)器法可以實(shí)現(xiàn)任意偶數(shù)分頻。在計(jì)數(shù)周期達(dá)到分頻系數(shù)中間數(shù)值 (N/2-1) 時(shí)進(jìn)行時(shí)鐘翻轉(zhuǎn),可保證分頻后時(shí)鐘的占空比為 50%。
Tips:中間數(shù)值(N/2-1) 需要減1是因?yàn)閺?開始計(jì)數(shù)
以六分頻為例,電路需要實(shí)現(xiàn)的是:計(jì)數(shù)器從0開始計(jì)數(shù)至2,計(jì)數(shù)器到0時(shí)信號(hào)翻轉(zhuǎn),具體的時(shí)序圖如下(圖由TimeGen繪制,該軟件功能實(shí)用,推薦使用)。
因?yàn)槭桥紨?shù)分頻,只要對(duì)分頻系數(shù)中間數(shù)值進(jìn)行循環(huán)計(jì)數(shù),在對(duì)應(yīng)的地方讓信號(hào)進(jìn)行反轉(zhuǎn)即可得到任意分頻的分頻器。
2.3 verilog代碼
//偶數(shù)分頻電路設(shè)計(jì)(2分頻、4分頻、8分頻、6分頻)
//觸發(fā)器法實(shí)現(xiàn)2分頻、4分頻、8分頻
//計(jì)數(shù)器法實(shí)現(xiàn)6分頻
module clk_div_even(
input rst_n, //復(fù)位信號(hào)
input clk, //源時(shí)鐘信號(hào)
output clk_div2, //輸出2分頻
output clk_div4, //輸出4分頻
output clk_div6, //輸出6分頻
output clk_div8 //輸出8分頻
);
//定義4個(gè)中間寄存器和1個(gè)計(jì)數(shù)器
reg clk_div2_r;
reg clk_div4_r;
reg clk_div6_r;
reg clk_div8_r;
reg [3:0] cnt;
//2分頻時(shí)鐘輸出模塊
//源時(shí)鐘上升沿觸發(fā),低電平異步復(fù)位
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin //低電平復(fù)位
clk_div2_r <= 1'b0;
end
else begin
clk_div2_r <= ~clk_div2_r; //源時(shí)鐘上升沿信號(hào)翻轉(zhuǎn)得到2分頻時(shí)鐘
end
end
assign clk_div2 = clk_div2_r; //延時(shí)輸出,消除亞穩(wěn)態(tài)
//4分頻時(shí)鐘輸出模塊
//2分頻時(shí)鐘上升沿觸發(fā) 低電平異步復(fù)位
always @(posedge clk_div2 or negedge rst_n) begin
if (!rst_n) begin
clk_div4_r <= 1'b0;
end
else begin
clk_div4_r <= ~clk_div4_r; //2分頻時(shí)鐘上升沿信號(hào)翻轉(zhuǎn)得到4分頻時(shí)鐘
end
end
assign clk_div4 = clk_div4_r; //延時(shí)輸出,消除亞穩(wěn)態(tài)
//8分頻時(shí)鐘輸出模塊
//4分頻時(shí)鐘上升沿觸發(fā) 低電平異步復(fù)位
always @(posedge clk_div4 or negedge rst_n) begin
if (!rst_n) begin
clk_div8_r <= 'b0;
end
else begin
clk_div8_r <= ~clk_div8_r; //4分頻時(shí)鐘上升沿信號(hào)翻轉(zhuǎn)得到8分頻時(shí)鐘
end
end
assign clk_div8 = clk_div8_r; //延時(shí)輸出,消除亞穩(wěn)態(tài)
//計(jì)數(shù)器模塊
//源時(shí)鐘上升沿觸發(fā),低電平異步復(fù)位
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin //低電平復(fù)位
cnt <= 4'b0 ;
end
else if (cnt == 2) begin //計(jì)數(shù)器從0計(jì)數(shù),到2清零
cnt <= 4'b0 ;
end
else begin //計(jì)數(shù)累加
cnt <= cnt + 1'b1 ;
end
end
//6分頻時(shí)鐘輸出模塊
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_div6_r <= 1'b0;
end
else if (cnt == 2 ) begin //3個(gè)周期信號(hào)翻轉(zhuǎn)得到6分頻時(shí)鐘
clk_div6_r <= ~clk_div6_r;
end
end
assign clk_div6 = clk_div6_r; //延時(shí)輸出,消除亞穩(wěn)態(tài)
endmodule
2.4 Testbench
`timescale 1ns/1ns //時(shí)間刻度:?jiǎn)挝?ns,精度1ns
module clk_div_even_tb;
//信號(hào)申明
reg clk ;
reg rst_n;
wire clk_div2;
wire clk_div4;
wire clk_div6;
wire clk_div8;
//定義源時(shí)鐘信號(hào)一周期時(shí)間
parameter DIV_CLK = 10;
//復(fù)位信號(hào)生成
initial begin
clk = 0; //時(shí)鐘信號(hào)賦初值
rst_n = 1; //復(fù)位信號(hào)賦初值
#(1.5*DIV_CLK) rst_n = 0;
#DIV_CLK rst_n = 1;
#(30*DIV_CLK);
end
//源時(shí)鐘信號(hào)生成
always #(DIV_CLK/2) clk = ~ clk;
//模塊例化
clk_div_even u_clk_div_even
(
.clk (clk),
.rst_n (rst_n),
.clk_div2 (clk_div2),
.clk_div4 (clk_div4),
.clk_div6 (clk_div6),
.clk_div8 (clk_div8)
);
endmodule
2.5 仿真結(jié)果
三、奇數(shù)分頻
3.1 占空比非50%奇數(shù)分頻
若要實(shí)現(xiàn)N分頻(N為奇數(shù)),只需將計(jì)數(shù)器在待分頻時(shí)鐘上升沿觸發(fā)循環(huán)計(jì)數(shù),計(jì)數(shù)到0時(shí)輸出時(shí)鐘翻轉(zhuǎn),當(dāng)計(jì)數(shù)到(N-1)/2后再次將輸出時(shí)鐘翻轉(zhuǎn)。
以三分頻為例,電路需要實(shí)現(xiàn)的是:計(jì)數(shù)器從0開始計(jì)數(shù)至2,計(jì)數(shù)器到0時(shí)且在上升沿信號(hào)翻轉(zhuǎn),計(jì)數(shù)器到1時(shí)且在上升沿信號(hào)清零,具體的時(shí)序圖如下(圖由TimeGen繪制,該軟件功能實(shí)用,推薦使用)。
3.2 占空比50%奇數(shù)分頻
如果對(duì)于占空比要求不高的話,只需要簡(jiǎn)單地對(duì)信號(hào)計(jì)數(shù)并且在對(duì)應(yīng)的計(jì)數(shù)器位置上升沿觸發(fā)信號(hào)翻轉(zhuǎn)即可以得到一個(gè)奇數(shù)分頻,此奇數(shù)分頻往往占空比達(dá)不到50%的要求。
那么如何得到一個(gè)50%占空比的奇數(shù)分頻呢?
從50%占空比奇數(shù)分頻波形看,信號(hào)的翻轉(zhuǎn)對(duì)應(yīng)的源時(shí)鐘信號(hào)分別是上升沿和下降沿,但是雙邊沿觸發(fā)在電路設(shè)計(jì)的時(shí)候是不允許的。
那么如何實(shí)現(xiàn)這種“類雙邊沿觸發(fā)”的效果呢?
對(duì)于50%占空比奇數(shù)分頻,就是分別利用待分頻時(shí)鐘的上升沿觸發(fā)生成一個(gè)時(shí)鐘,然后用下降沿觸發(fā)生成另一個(gè)時(shí)鐘,然后將兩個(gè)時(shí)鐘信號(hào)進(jìn)行或/與運(yùn)算得到占空比為50%的奇數(shù)分頻。
以三分頻為例,電路需要實(shí)現(xiàn)的是:設(shè)計(jì)2個(gè)分別用上升、下降沿觸發(fā)的計(jì)數(shù)器cnt_p和cnt_n,設(shè)計(jì)2個(gè)分別用上升、下降沿觸發(fā)的計(jì)數(shù)器clk_p和clk_n,利用clk_p和clk_n通過或邏輯運(yùn)算生成占空比為50%的分頻時(shí)鐘,具體的時(shí)序圖如下(圖由TimeGen繪制,該軟件功能實(shí)用,推薦使用)。
此處我們通過兩個(gè)計(jì)數(shù)器分別對(duì)上升沿和下降沿信號(hào)進(jìn)行翻轉(zhuǎn),最后通過或運(yùn)算得到占空比50%的分屏信號(hào)。
Tips:此處亦可借用與邏輯運(yùn)算,對(duì)比上面的clk_p和clk_n稍稍不同,大家可以試著自己畫出對(duì)應(yīng)時(shí)序圖。
3.3 Verilog代碼
//奇數(shù)分頻電路設(shè)計(jì)(占空比非50%的3分頻和占空比50%的3分頻)
module clk_div_odd (
input clk, //時(shí)鐘信號(hào)
input rst_n, //復(fù)位信號(hào)
output clk_div3_1, //占空比非50%的3分頻時(shí)鐘信號(hào)輸出
output clk_div3_2 //占空比50%的3分頻時(shí)鐘信號(hào)輸出
);
//定義分頻的數(shù)目
parameter N = 3;
reg [3:0] cnt_p; //上升沿觸發(fā)計(jì)數(shù)器計(jì)數(shù)
reg [3:0] cnt_n; //下降沿觸發(fā)計(jì)數(shù)器計(jì)數(shù)
reg clk_p; //上升沿觸發(fā)生成的時(shí)鐘信號(hào)
reg clk_n; //下降沿觸發(fā)生成的時(shí)鐘信號(hào)
//上升沿觸發(fā)計(jì)數(shù)器模塊
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt_p <= 4'b0000;
else if (cnt_p == N-1) //計(jì)數(shù)器從0計(jì)數(shù),到2清零
cnt_p <= 4'b0000;
else
cnt_p <= cnt_p + 1'b1; //計(jì)數(shù)器累加
end
//下降沿觸發(fā)計(jì)數(shù)器模塊
always @(negedge clk or negedge rst_n) begin
if(!rst_n)
cnt_n <= 4'b0000;
else if(cnt_n == N-1) //計(jì)數(shù)器從0計(jì)數(shù),到2清零
cnt_n <= 4'b0000;
else
cnt_n <= cnt_n + 1'b1; //計(jì)數(shù)器累加
end
//上升沿觸發(fā)生成的時(shí)鐘信號(hào)模塊
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
clk_p <= 1'b0;
else if(cnt_p == (N-1)/2) //計(jì)數(shù)器到1且在上升沿,時(shí)鐘信號(hào)翻轉(zhuǎn)
clk_p <= ~clk_p;
else if (cnt_p <= 0) //計(jì)數(shù)器到0且在上升沿,時(shí)鐘信號(hào)翻轉(zhuǎn)
clk_p <= ~clk_p;
else
clk_p <= clk_p; //防止latch產(chǎn)生
end
//下降沿觸發(fā)生成的時(shí)鐘信號(hào)模塊
always @(negedge clk or negedge rst_n)
begin
if(!rst_n)
clk_n <= 1'b0;
else if (cnt_n == (N-1)/2) //計(jì)數(shù)器到1且在上升沿,時(shí)鐘信號(hào)翻轉(zhuǎn)
clk_n <= ~clk_n;
else if (cnt_n == 0) //計(jì)數(shù)器到0且在上升沿,時(shí)鐘信號(hào)翻轉(zhuǎn)
clk_n <= ~clk_n;
else
clk_n <= clk_n; //防止latch產(chǎn)生
end
//延時(shí)輸出,消除亞穩(wěn)態(tài)
assign clk_div3_1 = clk_p; //得到占空比非50%的3分頻時(shí)鐘信號(hào)
assign clk_div3_2 = clk_p | clk_n; //或邏輯運(yùn)算得到占空比50%的3分頻時(shí)鐘信號(hào)
endmodule
3.4 Testbench
`timescale 1ns/1ps //時(shí)間刻度:?jiǎn)挝?ns,精度1ps
module clk_div_odd_tb;
//信號(hào)申明
reg clk;
reg rst_n;
wire clk_div3_1; //占空比非50%的3分頻時(shí)鐘信號(hào)
wire clk_div3_2; //占空比50%的3分頻時(shí)鐘信號(hào)
parameter DIV_CLK = 5; //定義源時(shí)鐘信號(hào)一周期時(shí)間
//復(fù)位信號(hào)生成
initial begin
clk = 0; //時(shí)鐘信號(hào)賦初值
rst_n = 1; //復(fù)位信號(hào)賦初值
#(3*DIV_CLK)
rst_n = 0;
#(6*DIV_CLK)
rst_n = 1;
#(20*DIV_CLK);
end
//源時(shí)鐘信號(hào)生成
always #DIV_CLK clk = ~clk;
//模塊例化
clk_div_odd u_clk_div_odd
(.clk (clk),
.rst_n (rst_n),
.clk_div3_1 (clk_div3_1),
.clk_div3_2 (clk_div3_2)
);
endmodule
3.5 仿真結(jié)果
四、小數(shù)分頻
4.1 雙模前置分頻法
不規(guī)整的小數(shù)分頻不能做到分頻后的每個(gè)時(shí)鐘周期都是源時(shí)鐘周期的小數(shù)分頻倍,更不能做到分頻后的時(shí)鐘占空比均為 50%,因?yàn)?Verilog 不能對(duì)時(shí)鐘進(jìn)行小數(shù)計(jì)數(shù)。
小數(shù)分頻是基于可變分頻和多次平均的方法實(shí)現(xiàn)的。
例如進(jìn)行5.4倍分頻,則保證源時(shí)鐘54個(gè)周期的時(shí)間等于分頻時(shí) 10個(gè)周期的時(shí)間即可。此時(shí)需要在54個(gè)源時(shí)鐘周期內(nèi)進(jìn)行6次5分頻,4次6分頻。
T = ( Ma+(M+1)b )/ a+b,這里我們發(fā)現(xiàn)組成小數(shù)分頻使用了a個(gè)M分頻和b個(gè)M+1分頻的整數(shù)分頻電路。
以 5.4 倍分頻為例:
基本思想是在54個(gè)源時(shí)鐘周期里完成10個(gè)5.4分頻,根據(jù)前面的公式可知:有6的5分頻和4個(gè)6分頻。只要將5分頻和6分頻插入在54個(gè)源時(shí)鐘周期即可。
同時(shí)我們應(yīng)當(dāng)考慮分頻信號(hào)的實(shí)現(xiàn)順序
5分頻和6分頻的實(shí)現(xiàn)順序一般有以下 4 種:
(1)先進(jìn)行 6 次 5 分頻,再進(jìn)行 4 次 6 分頻;
(2) 先進(jìn)行 4 次 6分頻,再進(jìn)行 6 次 5 分頻;
(3) 將 6 次 5 分頻平均的插入到 4 次 6 分頻中;
(4) 將 4 次 6 分頻平均的插入到 6 次 5 分頻中。
前兩種方法時(shí)鐘頻率不均勻,相位抖動(dòng)較大,所以一般會(huì)采用后兩種平均插入的方法進(jìn)行小數(shù)分頻操作。
那又如何平均插入呢?
平均插入可以通過分頻次數(shù)差累計(jì)的方法實(shí)現(xiàn),5.4 分頻的實(shí)現(xiàn)過程如下:
(1) 第一次分頻次數(shù)差值 54 - 10×5 = 4 < 10,第一次進(jìn)行 5 分頻。
(2) 第二次差值累加結(jié)果為 4+4=8 < 10,第二次使用 5 分頻,同時(shí)差值修改為(54-10×5) + (54 -10×5) = 8 。
(3) 第三次差值累加結(jié)果為 4 + 8 = 12 > 10,第三次使用 6分頻。
(4) 第四次差值累加結(jié)果為 12 + (54-10×6) < 10,第四次使用 5 分頻。
以此類推,完成將 6 次 5分頻平均插入到 4 次 6分頻的過程
具體的時(shí)序圖如下(圖由TimeGen繪制,該軟件功能實(shí)用,推薦使用),此時(shí)相位抖動(dòng)相對(duì)較小。
Tips:每一段并不是嚴(yán)格的5.4分頻(因?yàn)樾盘?hào)翻轉(zhuǎn)只在邊沿觸發(fā)),而是在54個(gè)源時(shí)鐘周期平均下來有10個(gè)分頻,而且時(shí)序難以保證。且占空比幾乎達(dá)不到50%。
4.2 Verilog代碼
//小數(shù)分頻電路設(shè)計(jì)
//雙模前置法實(shí)現(xiàn)5.4分頻
module clk_div_fraction
(
input rst_n, //復(fù)位信號(hào)
input clk, //時(shí)鐘信號(hào)
output clk_frac //小數(shù)分頻輸出信號(hào)
);
//定義介于5.4分頻的5分頻和6分頻
parameter CLK_DIV_1 = 5;
parameter CLK_DIV_2 = 6;
parameter DIFF = 4; //10個(gè)周期內(nèi)5分頻與5.4分頻的差值
reg [3:0] cnt_end; //分頻插入計(jì)數(shù)器 (用于判斷插入什么分頻)
reg [3:0] cnt; //總計(jì)數(shù)器
reg clk_frac_r; //小數(shù)分頻中間寄存器信號(hào)
reg [4:0] diff_cnt_r; //差值信號(hào)
reg [4:0] diff_cnt; //差值信號(hào)
wire diff_cnt_en= cnt == cnt_end; //使能信號(hào)
//差值累加邏輯模塊
always @(*) begin
if(diff_cnt_r >= 10) begin
diff_cnt = diff_cnt_r -10 + DIFF; //差值大于10,插入6分頻,差值減6
end
else begin
diff_cnt = diff_cnt_r + DIFF; //差值小于10,插入5分頻,差值加4
end
end
// 借用寄存器延遲輸出diff_cnt_r
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin //復(fù)位差值清零
diff_cnt_r <= 0;
end
else if(diff_cnt_en) begin //使能信號(hào)高電平時(shí),差值信號(hào)延遲輸出
diff_cnt_r <= diff_cnt;
end
end
//5分頻和6分頻插入邏輯模塊
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_end <= CLK_DIV_1-1 ; //復(fù)位先插入5分頻
end
else if(diff_cnt >= 10) begin
cnt_end <= CLK_DIV_2-1 ; //差值大于10,插入6分頻
end
else begin
cnt_end <= CLK_DIV_1-1 ; //差值小于10,插入5分頻
end
end
//
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin //總計(jì)數(shù)器、分頻信號(hào)信號(hào)復(fù)位
cnt <= 1'b0;
clk_frac_r <= 1'b0;
end
else if(cnt == cnt_end) begin //計(jì)數(shù)器到分頻插入界限點(diǎn)
cnt <= 1'b0; //總計(jì)數(shù)器清零
clk_frac_r <= 1'b1; //時(shí)鐘分頻信號(hào)電平置"1"
end
else begin //其他情況下,計(jì)數(shù)器累加計(jì)數(shù)、時(shí)鐘分頻信號(hào)電平保持"0"
cnt <= cnt + 1'b1;
clk_frac_r <= 1'b0;
end
end
//延時(shí)輸出,消除亞穩(wěn)態(tài)
assign clk_frac = clk_frac_r;
endmodule
4.3 Testbench
`timescale 1ns/1ps //時(shí)間刻度:?jiǎn)挝?ns,精度1ps
module clk_div_fraction_tb;
//信號(hào)申明
reg clk;
reg rst_n;
wire clk_frac;
parameter DIV_CLK = 5; //定義源時(shí)鐘信號(hào)一周期時(shí)間
//復(fù)位信號(hào)生成
initial begin
clk = 0; //時(shí)鐘信號(hào)賦初值
rst_n = 1; //復(fù)位信號(hào)賦初值
#(3*DIV_CLK)
rst_n = 0;
#(6*DIV_CLK)
rst_n = 1;
#(20*DIV_CLK);
end
//源時(shí)鐘信號(hào)生成
always #DIV_CLK clk = ~clk;
//模塊例化
clk_div_fraction u_clk_div_fraction
(.clk (clk),
.rst_n (rst_n),
.clk_frac (clk_frac)
);
endmodule
4.4 仿真結(jié)果
把5.4小數(shù)分頻和2.6小數(shù)分頻進(jìn)行比較,圖一是5.4小數(shù)分頻仿真時(shí)序圖,可以看到波形較為整齊;圖二是2.6小數(shù)分頻仿真時(shí)序圖,可以看到波形較為雜亂;
Tips:5.4小數(shù)分頻并不是每一段都是均勻的長(zhǎng)度(即局部不滿足小數(shù)分頻,總體滿足小數(shù)分頻)
那么是什么原因造成的呢?
從前面的基本原理可以知道,通過雙模前置法得到的小數(shù)分頻波形是差強(qiáng)人意的,5.4小數(shù)分頻通過5分頻和6分頻差值得到,2.6小數(shù)分頻通過2分頻和3分頻差值得到,同樣差一個(gè)cnt,對(duì)于2.6小數(shù)分頻的波形破壞要比5.4小數(shù)分頻要嚴(yán)重??偠灾褪牵壕植坎粷M足小數(shù)分頻,總體滿足小數(shù)分頻。
五、半整數(shù)分頻
5.1 占空比50%半整數(shù)分頻
對(duì)于使用小數(shù)分頻法得到的,以3.5分頻為例,需要使用一個(gè)四分頻和一個(gè)三分頻,七個(gè)周期內(nèi),輸出兩個(gè)1,但是信號(hào)時(shí)序難以得到保障,時(shí)鐘信號(hào)的質(zhì)量得不到保證。
那有沒有新的方法可以優(yōu)化半整數(shù)分頻呢?
可以這樣實(shí)現(xiàn)半整數(shù)分頻:
(1)在源時(shí)鐘上升沿分別產(chǎn)生由 4 個(gè)和 3 個(gè)源時(shí)鐘周期組成的 2 個(gè)分頻時(shí)鐘。
(2)在源時(shí)鐘下降沿分別產(chǎn)生由 4 個(gè)和 3 個(gè)源時(shí)鐘周期組成的 2 個(gè)分頻時(shí)鐘。
(3)兩個(gè)分頻時(shí)鐘做相位一個(gè)延遲半個(gè)源時(shí)鐘周期,一個(gè)提前半個(gè)源時(shí)鐘周期。將兩次產(chǎn)生的時(shí)鐘進(jìn)行“或”操作,便可以得到周期均勻的 3.5 倍分頻時(shí)鐘。分頻波形示意圖如下所示。
5.2 Verilog代碼
//半整數(shù)分頻電路設(shè)計(jì)
module clk_div_half
(
input rst_n,
input clk,
output clk_div
);
parameter DIV_CLK = 7; //3.5分頻的高低電平總個(gè)數(shù)
reg [3:0] cnt; //總計(jì)數(shù)器
reg clk_p; //上升沿觸發(fā)生成的時(shí)鐘信號(hào)
reg clk_n; //下降沿觸發(fā)生成的時(shí)鐘信號(hào)
//計(jì)數(shù)器模塊
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 1'b0 ;
end
else if (cnt == DIV_CLK-1) begin //從0計(jì)數(shù),到6清零
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
//上升沿觸發(fā)生成的時(shí)鐘信號(hào)模塊
//計(jì)數(shù)器到0和4并且在上升沿觸發(fā)信號(hào)翻轉(zhuǎn)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
clk_p <= 1'b0;
end
else if (cnt == 0) begin //計(jì)數(shù)器到0信號(hào)翻轉(zhuǎn)
clk_p <= 1;
end
else if (cnt == (DIV_CLK/2)+1) begin //計(jì)數(shù)器到4信號(hào)翻轉(zhuǎn)
clk_p <= 1 ;
end
else begin
clk_p <= 0 ;
end
end
//下降沿觸發(fā)生成的時(shí)鐘信號(hào)模塊
//計(jì)數(shù)器到1和4并且在下降沿觸發(fā)信號(hào)翻轉(zhuǎn)
always@(negedge clk or negedge rst_n) begin
if(!rst_n) begin
clk_n <= 1'b0 ;
end
else if(cnt == 1) begin //計(jì)數(shù)器到1信號(hào)翻轉(zhuǎn)
clk_n <= 1 ;
end
else if (cnt == (DIV_CLK/2)+1 ) begin //計(jì)數(shù)器到4信號(hào)翻轉(zhuǎn)
clk_n<= 1 ;
end
else begin
clk_n <= 0 ;
end
end
//或邏輯運(yùn)算得到占空比50%的3.5半整數(shù)分頻信號(hào)
assign clk_div = clk_p | clk_n;
endmodule
5.3 Testbench
`timescale 1ns/1ps //時(shí)間刻度:?jiǎn)挝?ns,精度1ps
module clk_div_half_tb;
//信號(hào)申明
reg clk;
reg rst_n;
wire clk_div;
parameter DIV_CLK0 = 5; //定義源時(shí)鐘信號(hào)一周期時(shí)間
//復(fù)位信號(hào)生成
initial begin
clk = 0; //時(shí)鐘信號(hào)賦初值
rst_n = 1; //復(fù)位信號(hào)賦初值
#(3*DIV_CLK0)
rst_n = 0;
#(6*DIV_CLK0)
rst_n = 1;
#(20*DIV_CLK0);
end
//源時(shí)鐘信號(hào)生成
always #DIV_CLK0 clk = ~clk;
//模塊例化
clk_div_half u_clk_div_half
(.clk (clk),
.rst_n (rst_n),
.clk_div (clk_div)
);
endmodule
5.4仿真結(jié)果
六、狀態(tài)機(jī)分頻
6.1狀態(tài)機(jī)分頻
Verilog 中狀態(tài)機(jī)主要用于同步時(shí)序邏輯的設(shè)計(jì),能夠在有限個(gè)狀態(tài)之間按一定要求和規(guī)律切換時(shí)序電路的狀態(tài)。狀態(tài)的切換方向不但取決于各個(gè)輸入值,還取決于當(dāng)前所在狀態(tài)。狀態(tài)機(jī)可分為 2 類:Moore 狀態(tài)機(jī)和 Mealy 狀態(tài)機(jī)。
例如完成一個(gè)四分頻且占空比為25%的分頻器,此時(shí)可以列出四種狀態(tài),狀態(tài)機(jī)在四種狀態(tài)不斷切換,根據(jù)下一個(gè)輸出狀態(tài)只與當(dāng)前狀態(tài)有關(guān)而與輸出無關(guān),可以知道此分頻器可根據(jù)Moore狀態(tài)機(jī)完成。
6.2 verilog代碼
module clk_div_FSM
(
input wire clk,
input wire rst_n,
output reg clk_FSM
);
//定義四種狀態(tài)
parameter S0 = 2'b00;
parameter S1 = 2'b01;
parameter S2 = 2'b10;
parameter S3 = 2'b11;
reg [1:0] state; //定義目前狀態(tài)
reg [1:0] next_state; //下一狀態(tài)
//信號(hào)復(fù)位模塊
always @(posedge clk,negedge rst_n) begin
if(!rst_n) begin
state <= S0;
end
else begin
state <= next_state;
end
end
//狀態(tài)轉(zhuǎn)換模塊(相當(dāng)于用狀態(tài)機(jī)寫計(jì)數(shù)器)
always @(*) begin
case (state)
S0: next_state = S1;
S1: next_state = S2;
S2: next_state = S3;
S3: next_state = S0;
endcase
end
//信號(hào)輸出模塊
always @(*) begin
if(state == S0) begin
clk_FSM = 1'b1;
end
else begin
clk_FSM = 1'b0;
end
end
endmodule
6.3 Tsetbench
`timescale 1ns/1ps
module clk_div_FSM_tb;
//信號(hào)申明
reg clk;
reg rst_n;
wire clk_FSM;
parameter DIV_CLK = 5; //定義源時(shí)鐘信號(hào)一周期時(shí)間
//復(fù)位信號(hào)生成
initial begin
clk = 0; //時(shí)鐘信號(hào)賦初值
rst_n = 1; //復(fù)位信號(hào)賦初值
#(3*DIV_CLK)
rst_n = 0;
#(6*DIV_CLK)
rst_n = 1;
#(20*DIV_CLK);
end
//源時(shí)鐘信號(hào)生成
always #DIV_CLK clk = ~clk;
//模塊例化
clk_div_FSM u_clk_div_FSM
(.clk (clk),
.rst_n (rst_n),
.clk_FSM (clk_FSM)
);
endmodule
6.4仿真結(jié)果
七、總結(jié)
偶數(shù)分頻:無論是通過D觸發(fā)器還是計(jì)數(shù)器實(shí)現(xiàn),這類分頻都是最容易得到的,并且占空比容易控制在50%。對(duì)于D觸發(fā)器實(shí)現(xiàn)偶數(shù)分頻來說,分頻數(shù)只能得2^n,其余分頻數(shù)只能由計(jì)數(shù)器法等其他方法實(shí)現(xiàn)。除此以外,隨著分頻的數(shù)目不斷增大,通過D觸發(fā)器實(shí)現(xiàn)觸發(fā)器數(shù)目會(huì)增多,在電路設(shè)計(jì)的過程中應(yīng)當(dāng)考慮面積因素。對(duì)于計(jì)數(shù)器實(shí)現(xiàn)偶數(shù)分頻,占空比和分頻數(shù)都可以得到極大的控制,是實(shí)現(xiàn)偶數(shù)分頻最靈活的一種方式。
奇數(shù)分頻:計(jì)數(shù)分頻基本原理也是通過計(jì)數(shù)器實(shí)現(xiàn)的,主要分為占空比非50%的奇數(shù)分頻和占空比50%的奇數(shù)分頻,后者實(shí)現(xiàn)簡(jiǎn)單而后者稍稍復(fù)雜一些。占空比非50%的情況下,時(shí)鐘信號(hào)在上升沿(N-1)/2翻轉(zhuǎn)和 0翻轉(zhuǎn)即可得到需要的分頻信號(hào)。占空比50%的情況下,一個(gè)時(shí)鐘信號(hào)在上升沿而一個(gè)時(shí)鐘信號(hào)在下降沿,觸發(fā)(N-1)/2翻轉(zhuǎn)和0翻轉(zhuǎn),然后將clk_p和clk_n做或邏輯運(yùn)算即可得到占空比50%的計(jì)數(shù)分頻信號(hào)。從以上可以看出,占空比50%的奇數(shù)分頻只是在占空比非50%的奇數(shù)分頻的基礎(chǔ)上多做了一個(gè)邏輯運(yùn)算。
小數(shù)分頻:目前小數(shù)分頻使用較多的方法是雙模前置分頻法,基本原理是在小數(shù)分頻的兩側(cè)尋找相近的分頻去插入,營(yíng)造在一定的源時(shí)鐘周期走過與小數(shù)分頻相當(dāng)?shù)牡臅r(shí)鐘周期。但是往往分頻的時(shí)序波形比較亂,占空比幾乎達(dá)不到50%,效果差強(qiáng)人意,究其根本原因是信號(hào)只在源時(shí)鐘的邊沿觸發(fā)。
半整數(shù)分頻:半整數(shù)分頻是小數(shù)分頻的特殊情況,之所以會(huì)拎出來單獨(dú)講,是因?yàn)楦鶕?jù)小數(shù)分頻的雙模前置法做出來的波形時(shí)序較差。如果需要得50%的半整數(shù)分頻怎么辦? 首先做出兩個(gè)上升沿和下降沿二分頻信號(hào),通過在半整數(shù)兩邊尋找相鄰的的奇數(shù)和偶數(shù)(決定信號(hào)電平周期數(shù)),然后做邏輯運(yùn)算即可以得到占空比50%的半整數(shù)分頻。
狀態(tài)機(jī)分頻:可以實(shí)現(xiàn)分頻的方式之一,對(duì)于簡(jiǎn)單的分頻器可以采用狀態(tài)機(jī)來實(shí)現(xiàn),大部分情況狀態(tài)機(jī)用來處理較為復(fù)雜的情況與問題,在分頻電路里有大材小用的感覺,電路分頻時(shí)可以采用更簡(jiǎn)單的計(jì)數(shù)器代替狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)換。
不定期檢查、補(bǔ)充、糾錯(cuò),歡迎隨時(shí)交流糾錯(cuò)
最后修改日期:2023.5.10文章來源:http://www.zghlxwxcb.cn/news/detail-443572.html
軟件版本:文章來源地址http://www.zghlxwxcb.cn/news/detail-443572.html
- 仿真軟件:Modelsim 10.6c
- 時(shí)序繪制軟件:TimeGen 3.2
- 描述語(yǔ)言:verilog
到了這里,關(guān)于數(shù)字分頻器設(shè)計(jì)(偶數(shù)分頻、奇數(shù)分頻、小數(shù)分頻、半整數(shù)分頻、狀態(tài)機(jī)分頻|verilog代碼|Testbench|仿真結(jié)果)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!