|
一、異步信號同步器設計
1、復位的設計:采用異步復位,同步釋放電路
http://www.cnblogs.com/qiweiwang/archive/2010/11/25/1887888.html
2、異步信號同步器:
http://www./analog/apply/ybxhtbqsj_60096_2.html
?、匐娖酵狡?/p>
1 module synzer_ls(
2 data_out,
3 clk1,
4 clk2,
5 data_in
6 ); //level signal synchronizer
7
8 output data_out; // signal that after synchronized
9 input clk1; // old clk signal
10 input clk2; // new clk signal
11 input data_in; // signal that before synchronized
12
13 reg a; // DFF in the old clk domain
14 reg b; // the first DFF in the new clk domain
15 reg c; // the second DFF in the new clk domain
16
17 always @(posedge clk1) //a
18 a<=data_in;
19
20 always @(posedge clk2) //b
21 b<=a;
22
23 always @(posedge clk2) //c
24 c<=b;
25
26 assign data_out=c;
27
28 endmodule
?、谶呇貦z測同步器
1 module synzer_ed(
2 data_out,
3 clk1,
4 clk2,
5 data_in
6 ); // edge detecting synchronizer
7
8 output data_out; // signal that after synchronized
9 input clk1; // old clk signal
10 input clk2; // new clk signal
11 input data_in; // signal that before synchronized
12
13 reg a; // DFF in the old clk domain
14 reg b; // the first DFF in the new clk domain
15 reg c; // the second DFF in the new clk domain
16 reg d; // the third DFF in the new clk domain
17
18 always @(posedge clk1) //a
19 a<=data_in;
20
21 always @(posedge clk2) //b
22 b<=a;
23
24 always @(posedge clk2) //c
25 c<=b;
26
27 always @(posedge clk2) //d
28 d<=c;
29
30 assign data_out=c&&(~d);
31
32 endmodule
③脈沖檢測同步器
1 module synzer_pl(
2 data_out,
3 clk1,
4 clk2,
5 data_in,
6 rst_n
7 ); // pulse synchronizer
8
9 output data_out; // signal that after synchronized
10 input clk1; // old clk signal
11 input clk2; // new clk signal
12 input data_in; // signal that before synchronized
13 input rst_n; // signal indicating reset
14
15 reg a; // DFF in the old clk domain
16 reg b; // the first DFF in the new clk domain
17 reg c; // the second DFF in the new clk domain
18 reg d; // the third DFF in the new clk domain
19
20 wire q;
21 wire q1;
22 wire di;
23
24 assign di=data_in?q1:q;
25 assign q=a;
26 assign q1=~a;
27 assign data_out=(c==d)?0:1;
28
29 always @(posedge clk1) //a
30 begin
31 if(!rst_n)
32 a<=1'b0;
33 else
34 a<=di;
35 end
36
37 always @(posedge clk2) //b
38 b<=a;
39
40 always @(posedge clk2) //c
41 c<=b;
42
43 always @(posedge clk2) //d
44 d<=c;
45
46 endmodule
二、常用觸發(fā)器實現(xiàn)
http://www./article/08-03/37231s.html
2.6.1 Verilog基本模塊
1.觸發(fā)器的Verilog實現(xiàn)
時序電路是高速電路的主要應用類型,其特點是任意時刻電路產生的穩(wěn)定輸出不僅與當前的輸入有關,而且還與電路過去時刻的輸入有關。時序電路的基本單元就是觸發(fā)器。下面介紹幾種常見同步觸發(fā)器的Verilog實現(xiàn)。
RS觸發(fā)器分為同步觸發(fā)器和異步觸發(fā)器,二者的區(qū)別在于同步觸發(fā)器有一個時鐘端clk,只有在時鐘端的信號上升(正觸發(fā))或下降(負觸發(fā))時,觸發(fā)器的輸出才會發(fā)生變化。下面以正觸發(fā)為例,給出其Verilog代碼實現(xiàn)。
例2-15 正觸發(fā)型同步RS觸發(fā)器的Verilog實現(xiàn)。
module sy_rs_ff (clk, r, s, q, qb); input clk, r, s; output q, qb; reg q;
assign qb = ~ q; always @(posedge clk) begin case({r, s}) 2'b00: q <= 0; 2'b01: q <= 1; 2'b10: q <= 0; 2'b11: q <= 1'bx; endcase end endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-2所示。

圖2-2 同步RS觸發(fā)器的RTL結構圖
在ModelSim 6.2b中完成仿真,其結果如圖2-3所示

圖2-3 同步RS觸發(fā)器的仿真結果示意圖
T觸發(fā)器也分為同步觸發(fā)器和異步觸發(fā)器,二者的區(qū)別在于同步T觸發(fā)器多了一個時鐘端。同步T觸發(fā)器的邏輯功能為:當時鐘clk沿到來時,如果T=0,則觸發(fā)器狀態(tài)保持不變;否則,觸發(fā)器輸出端反轉。R為復位端,當其為高電平時,輸出Q與時鐘無關,Q=0。
例2-16 同步T觸發(fā)器的Verilog實現(xiàn)。
module sy_t_ff(clk, r, t, q, qb); input clk, r, t; output q, qb; reg q;
assign qb = ~q; always @(posedge clk) begin if(r) q <= 0; else q <= ~q; end endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-4所示。

圖2-4 同步T觸發(fā)器電路的RTL結構圖
在ModelSim 6.2b中完成仿真,其結果如圖2-5所示

圖2-5 同步T觸發(fā)器的仿真結果示意圖
同步D觸發(fā)器的功能為: D輸入只能在時序信號clk的沿變化時才能被寫入到存儲器中,替換以前的值,常用于數據延遲以及數據存儲模塊中。
例2-17 同步D觸發(fā)器的Verilog實現(xiàn)。
module sy_d_ff(clk, d, q, qb); input clk, d; output q, qb; reg q;
assign qb = ~q; always @(posedge clk) begin q <= d; end endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-6所示。

圖2-6 同步D觸發(fā)器的RTL結構圖
在ModelSim 6.2b中完成仿真,其結果如圖2-7所示

圖2-7 同步D觸發(fā)器的仿真結果示意圖
JK觸發(fā)器是在RS觸發(fā)器的基礎上發(fā)展而來的,常用于實現(xiàn)計數器。當clk=0時,觸發(fā)器不工作,處于保持狀態(tài)。當時鐘clk=1時,觸發(fā)器的功能如下:當JK為00、01以及10時實現(xiàn)RS觸發(fā)器的功能;當JK為11時實現(xiàn)T觸發(fā)器的功能。
例2-18 同步JK觸發(fā)器的Verilog實現(xiàn)。
module sy_jk_ff(clk, j, k, q, qb); input clk, i, k; output q, qb; reg q;
assign qb = ~q; always @(posedge clk) begin case({j, k}) 2'b00: q <= q; 2'b01: q <= 0; 2'b10: q <= 1; 2'b11: q <= ~q; endcase end endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-8所示。

圖2-8 同步JK觸發(fā)器的RTL結構圖
在ModelSim 6.2b中完成仿真,其結果如圖2-9所示

圖2-9 同步JK觸發(fā)器的仿真結果示意圖
2.三態(tài)緩沖器的Verilog實現(xiàn)
三態(tài)緩沖器也稱三態(tài)門,其典型應用是雙向端口,常用于雙向數據總線的構建。在數字電路中,邏輯輸出有兩個正常態(tài):低電平狀態(tài)(對應邏輯0)和高電平狀態(tài)(對應邏輯1);此外,電路還有不屬于0和1狀態(tài)的高組態(tài)(對應于邏輯Z)。所謂高阻,即輸出端屬于浮空狀態(tài),只有很小的漏電流流動,其電平隨外部電平高低而定,門電平放棄對輸出電路的控制。或者可以理解為輸出與電路是斷開的。最基本的三態(tài)緩沖器的邏輯符號如圖2-10所示。
圖2-10 三態(tài)緩沖器的邏輯符號圖
當OE為高電平時,Dataout與Datain相連;而OE為低時,Dataout為高阻態(tài),相當于和Datain之間的連線斷開。
例2-19 使用Verilog實現(xiàn)三態(tài)緩沖器
inout a; wire z, b; //當控制信號z為1時,開通三態(tài)門,b為輸入端口;當z為0時,三態(tài)門為高阻, //a為輸出端口 assign a = (z) ? b : 8'bz;
3.38譯碼器的Verilog實現(xiàn)
38譯碼器是通過3條線來達到控制8條線的狀態(tài),就是通過3條控制線不同的高低電平組合, 一共可以組合出23=8種狀態(tài)。在電路中主要起到擴展IO資源的作用。當然,可根據實際需求將38譯碼器擴展到更高級數上。
例2-20 使用Verilog實現(xiàn)38譯碼器
module decoder3to8(din, reset, dout); input [2:0] din; input reset; output [7:0] dout;
reg [7:0] dout; always @(din or reset) begin if(!reset) dout = 8'b0000_0000; else case(din) 3'b000: dout = 8'b0000_0001; 3'b001: dout = 8'b0000_0010; 3'b010: dout = 8'b0000_0100; 3'b011: dout = 8'b0000_1000; 3'b100: dout = 8'b0001_0000; 3'b101: dout = 8'b0010_0000; 3'b110: dout = 8'b0100_0000; 3'b111: dout = 8'b1000_0000; endcase end
endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-11所示。

圖2-11 38譯碼器的RTL結構圖
在ModelSim 6.2b中完成仿真,其結果如圖2-12所示

圖2-12 38譯碼器的仿真結果示意圖
2.6.2 基本時序處理模塊
1.奇、偶數分頻電路
在數字邏輯電路設計中,分頻器是一種基本電路。通常用來對某個給定頻率進行分頻,以得到所需的頻率。
偶數倍分頻是最簡單的一種分頻模式,完全可通過計數器計數實現(xiàn)。如要進行N倍偶數分頻,那么可由待分頻的時鐘觸發(fā)計數器計數,當計數器從0計數到N/2-1時,輸出時鐘進行翻轉,并給計數器一個復位信號,使得下一個時鐘從零開始計數,以此循環(huán)下去。這種方法可以實現(xiàn)任意的偶數分頻。例2-21給出的是一個16分頻電路,其它倍數的分頻電路可通過修改計數器的上限值得到。
例2-21 用Verilog實現(xiàn)一個16分頻電路。
module clk_div16(clk_in, reset, clk_out); input clk_in; input reset; output clk_out;
reg clk_out; reg [2:0] cnt; always @(posedge clk_in) begin if(!reset) begin cnt <= 0; clk_out <= 0; end else if(cnt == 7) begin cnt <= 0; clk_out <= !clk_out; end else begin cnt <= cnt + 1; clk_out <= clk_out; end end
endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-13所示。

圖2-13 16分頻電路的RTL結構圖
在ModelSim 6.2b中完成仿真,其結果如圖2-14所示,從中可以看出例2-21成功實現(xiàn)了輸入時鐘的16分頻。

圖2-14 16分頻電路的仿真結果示意圖
奇數倍分頻有多種實現(xiàn)方法,下面介紹常用的錯位“異或”法的原理。如進行三分頻,通過待分頻時鐘上升沿觸發(fā)計數器進行模三計數,當計數器計數到鄰近值進行兩次翻轉。比如在計數器計數到1時,輸出時鐘進行翻轉,計數到2時再次進行翻轉,即在鄰近的1和2時刻進行兩次翻轉。這樣實現(xiàn)的三分頻占空比為1/3或者2/3。如果要實現(xiàn)占空比為50%的三分頻時鐘,可以通過待分頻時鐘下降沿觸發(fā)計數,和上升沿同樣的方法計數進行三分頻,然后將下降沿產生的三分頻時鐘和上升沿產生的時鐘進行相或運算,即可得到占空比為50%的三分頻時鐘。 這種錯位“異或”法可以推廣實現(xiàn)任意的奇數分頻:對于實現(xiàn)占空比為50%的N倍奇數分頻,首先進行上升沿觸發(fā)的模N計數,計數到某一選定值時進行輸出時鐘翻轉,然后經過(N-1)/2再次進行翻轉得到一個占空比非50%奇數N分頻時鐘。再者同時進行下降沿觸發(fā)的模N計數,到和上升沿觸發(fā)輸出時鐘翻轉選定值相同值時,進行輸出時鐘時鐘翻轉,同樣經過(N-1)/2時,輸出時鐘再次翻轉生成占空比非50%的奇數N分頻時鐘。兩個占空比非50%的N分頻時鐘相或運算,得到占空比為50%的奇數N分頻時鐘。
例2-22 使用Verilog實現(xiàn)3分頻電路。
module clk_div3(clk_in, reset, clk_out); input clk_in; input reset; output clk_out;
reg [1:0] cnt, cnt1; reg clk_1to3p, clk_1to3n; always @(posedge clk_in) begin if(!reset) begin cnt <= 0; clk_1to3p <= 0; end else begin if(cnt == 2'b10) begin cnt <= 0; clk_1to3p <= clk_1to3p; end else begin cnt <= cnt + 1; clk_1to3p <= !clk_1to3p; end end end
always @(negedge clk_in) begin if(!reset) begin cnt1 <= 0; clk_1to3n <= 0; end else begin if(cnt1 == 2'b10) begin cnt1 <= 0; clk_1to3n <= clk_1to3n; end else begin cnt1 <= cnt1 + 1; clk_1to3n <= !clk_1to3n; end end end
assign clk_out = clk_1to3p | clk_1to3n;
endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-15所示。
圖2-15 3分頻電路的RTL結構圖
在ModelSim 6.2b中完成仿真,其結果如圖2-16所示,可以看到輸出時鐘為占空比為50%的3分頻時鐘。

圖2-16 3分頻電路的仿真結果
2.同步采樣模塊
在實際應用中,外部輸入的異步信號需要經過系統(tǒng)時鐘的同步化,且將輸入的異步信號整形成一個時鐘長的脈沖信號,如圖2-17所示。這里以例2-23來說明實現(xiàn)的方法。

圖2-17 異步信號的同步采樣示意圖
例2-23 使用Verilog將外部異步信號進行同步整形。
module clk_syn(clk, reset, s_in, s_out); input clk; input reset; input s_in; output s_out;
reg s_t1, s_t2; always @(posedge clk) begin if(!reset) begin s_t1 <= 0; s_t2 <= 0; end else begin s_t1 <= s_in; s_t2 <= s_t1; end end
assign s_out = s_t1 & (!s_t2);
endmodule
上述程序經過綜合Synplify Pro后,其RTL級結構如圖2-18所示。從結果上看,該電路非常簡單,但需要一定的時序邏輯能力才能真正理解該段程序。

圖2-18 同步電路的RTL結構示意圖
在ModelSim 6.2b中完成仿真,其結果如圖2-19所示,將不等長的高電平信號整形成寬度為一個時鐘周期的脈沖信號。

圖2-19 同步電路的仿真結果示意圖
其中,如果在時鐘的上升沿din="1",則x=1,y=0,dout=x and (not y)=1;如果din="1"超過一個時鐘寬度,則x=1,y=1,dout=x and (not y)=0。即使din在時鐘周期內出現(xiàn)抖動,也不會影響輸出結果,還是被整形成一個時鐘寬度。所以不管是長周期信號還是短周期信號,經過同步采樣后,有效高電平寬度都等于時鐘周期。
3.同步狀態(tài)機的Verilog實現(xiàn)
狀態(tài)機一般包括組合邏輯和寄存器邏輯兩部分。組合電路用于狀態(tài)譯碼和產生輸出信號,寄存器用于存儲狀態(tài)。狀態(tài)機的下一個狀態(tài)及輸出不僅與輸入信號有關,還與寄存器當前狀態(tài)有關。根據輸出信號產生方法的不同,狀態(tài)機可分為米里(Mealy)型和摩爾(Moore)型。前者的輸出是當前狀態(tài)和輸入信號的函數,后者的輸出僅是當前狀態(tài)的函數。在硬件設計時,根據需要決定采用哪種狀態(tài)機。
狀態(tài)編碼又稱狀態(tài)分配。通常有多種編碼方法,編碼方案選擇得當,設計的電路可以簡單;反之,電路會占用過多的邏輯或速度降低。設計時,須綜合考慮電路復雜度和電路性能這兩個因素。下面主要介紹二進制編碼、格雷編碼和獨熱碼。
二進制編碼和格雷碼都是壓縮狀態(tài)編碼。二進制編碼的優(yōu)點是使用的狀態(tài)向量最少,但從一個狀態(tài)轉換到相鄰狀態(tài)時,可能有多個比特位發(fā)生變化,瞬變次數多,易產生毛刺。格雷編碼在相鄰狀態(tài)的轉換中,每次只有1個比特位發(fā)生變化,雖減少了產生毛刺和一些暫態(tài)的可能,但不適用于有很多狀態(tài)跳轉的情況。
獨熱碼是指對任意給定的狀態(tài),狀態(tài)向量中只有1位為1,其余位都為0。n狀態(tài)的狀態(tài)機需要n個觸發(fā)器。這種狀態(tài)機的速度與狀態(tài)的數量無關,僅取決于到某特定狀態(tài)的轉移數量,速度很快。當狀態(tài)機的狀態(tài)增加時,如果使用二進制編碼,那么狀態(tài)機速度會明顯下降。而采用獨熱碼,雖然多用了觸發(fā)器,但由于狀態(tài)譯碼簡單,節(jié)省和簡化了組合邏輯電路。獨熱編碼還具有設計簡單、修改靈活、易于綜合和調試等優(yōu)點。對于寄存器數量多、而門邏輯相對缺乏的FPGA器件,采用獨熱編碼可以有效提高電路的速度和可靠性,也有利于提高器件資源的利用率。獨熱編碼有很多無效狀態(tài),應該確保狀態(tài)機一旦進入無效狀態(tài)時,可以立即跳轉到確定的已知狀態(tài)。
- 有限狀態(tài)機的Verilog實現(xiàn)
用Verilog 語言描述有限狀態(tài)機可使用多種風格,不同的風格會極大地影響電路性能。通常有3種描述方式:單always塊、雙always塊和三always塊。
單always塊把組合邏輯和時序邏輯用同一個時序always塊描述,其輸出是寄存器輸出,無毛刺。但是這種方式會產生多余的觸發(fā)器,代碼難于修改和調試,應該盡量避免使用。 雙always塊大多用于描述Mealy狀態(tài)機和組合輸出的Moore狀態(tài)機,時序always塊描述當前狀態(tài)邏輯,組合邏輯always塊描述次態(tài)邏輯并給輸出賦值。這種方式結構清晰,綜合后的面積和時間性能好。但組合邏輯輸出往往會有毛刺,當輸出向量作為時鐘信號時,這些毛刺會對電路產生致命的影響。 三always塊大多用于同步Mealy狀態(tài)機,兩個時序always塊分別用來描述現(xiàn)態(tài)邏輯和對輸出賦值,組合always塊用于產生下一狀態(tài)。這種方式的狀態(tài)機也是寄存器輸出,輸出無毛刺,并且代碼比單always塊清晰易讀,但是面積大于雙always塊。隨著芯片資源和速度的提高,目前這種方式得到了廣泛應用。 下面以三always塊模塊給出狀態(tài)機的Verilog模板。
// 構成狀態(tài)跳轉環(huán) always @(posedge clk or negedge rst_n) current_state <= next_state;
// 完成狀態(tài)機的內部邏輯 always @ (current_state or ) begin case(current_state) S1: next_state = S2; S2: next_state = S1; default: next_state = S2; endcase end
// 完成狀態(tài)機的外部邏輯 always @(current_state or ) begin case(current_state) S1: S2: default: endcase end
在硬件描述語言中,許多基于仿真的語句雖然符合語法規(guī)則,但是不能映射到硬件邏輯電路單元,如果要最終實現(xiàn)硬件設計,必須寫出可以綜合的程序。通常,綜合的原則為:
- 綜合之前一定要進行仿真,仿真會暴露邏輯錯誤。如果不做仿真,沒有發(fā)現(xiàn)的邏輯錯誤會進入綜合器,使綜合的結果產生同樣的邏輯錯誤。
- 每一次布線之后都要進行仿真,在器件編程或流片之前一定要進行最后的仿真。
- 用Verilog HDL描述的異步狀態(tài)機是不能綜合的,應該避免用綜合器來設計。在必須設計異步狀態(tài)機時,建議用電路圖輸入的方法
- 狀態(tài)機應該有一個異步或同步復位端,以便在通電時將硬件電路復位到有效狀態(tài)。建議使用異步復位以簡化硬件開銷。
- 時序邏輯電路建模時,用非阻塞賦值。用always塊寫組合邏輯時,采用阻塞賦值。不要在多個always塊中為同一個變量賦值。
- always塊中應該避免組合反饋回路。在賦值表達式右端參與賦值的信號都必須出現(xiàn)在敏感信號列表中,否則在綜合時,會為沒有列出的信號隱含地產生一個透明鎖存器。
三、其他
鑒相:

濾波:

|