一、異步信號同步器設(shè)計
1、復(fù)位的設(shè)計:采用異步復(fù)位,同步釋放電路
http://www.cnblogs.com/qiweiwang/archive/2010/11/25/1887888.html
2、異步信號同步器:
http://www.srvee.com/analog/apply/ybxhtbqsj_60096_2.html
①電平同步器
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 signal10 input clk2; // new clk signal11 input data_in; // signal that before synchronized12 13 reg a; // DFF in the old clk domain14 reg b; // the first DFF in the new clk domain15 reg c; // the second DFF in the new clk domain16 17 always @(posedge clk1) //a18 a<=data_in; 19 20 always @(posedge clk2) //b21 b<=a;22 23 always @(posedge clk2) //c24 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 signal10 input clk2; // new clk signal11 input data_in; // signal that before synchronized12 13 reg a; // DFF in the old clk domain14 reg b; // the first DFF in the new clk domain15 reg c; // the second DFF in the new clk domain16 reg d; // the third DFF in the new clk domain17 18 always @(posedge clk1) //a19 a<=data_in; 20 21 always @(posedge clk2) //b22 b<=a;23 24 always @(posedge clk2) //c25 c<=b;26 27 always @(posedge clk2) //d28 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 synchronized10 input clk1; // old clk signal11 input clk2; // new clk signal12 input data_in; // signal that before synchronized13 input rst_n; // signal indicating reset 14 15 reg a; // DFF in the old clk domain16 reg b; // the first DFF in the new clk domain17 reg c; // the second DFF in the new clk domain18 reg d; // the third DFF in the new clk domain19 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) //a30 begin31 if(!rst_n)32 a<=1'b0;33 else34 a<=di;35 end36 37 always @(posedge clk2) //b38 b<=a;39 40 always @(posedge clk2) //c41 c<=b;42 43 always @(posedge clk2) //d44 d<=c;45 46 endmodule
二、常用觸發(fā)器實現(xiàn)
http://www.eefocus.com/article/08-03/37231s.html
2.6.1 Verilog基本模塊
1.觸發(fā)器的Verilog實現(xiàn)
時序電路是高速電路的主要應(yīng)用類型,其特點是任意時刻電路產(chǎn)生的穩(wěn)定輸出不僅與當前的輸入有關(guān),而且還與電路過去時刻的輸入有關(guā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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-2所示。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖2-3所示
T觸發(fā)器也分為同步觸發(fā)器和異步觸發(fā)器,二者的區(qū)別在于同步T觸發(fā)器多了一個時鐘端。同步T觸發(fā)器的邏輯功能為:當時鐘clk沿到來時,如果T=0,則觸發(fā)器狀態(tài)保持不變;否則,觸發(fā)器輸出端反轉(zhuǎn)。R為復(fù)位端,當其為高電平時,輸出Q與時鐘無關(guān),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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-4所示。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖2-5所示
同步D觸發(fā)器的功能為: D輸入只能在時序信號clk的沿變化時才能被寫入到存儲器中,替換以前的值,常用于數(shù)據(jù)延遲以及數(shù)據(jù)存儲模塊中。
例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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-6所示。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖2-7所示
JK觸發(fā)器是在RS觸發(fā)器的基礎(chǔ)上發(fā)展而來的,常用于實現(xiàn)計數(shù)器。當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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-8所示。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖2-9所示
2.三態(tài)緩沖器的Verilog實現(xiàn)
三態(tài)緩沖器也稱三態(tài)門,其典型應(yīng)用是雙向端口,常用于雙向數(shù)據(jù)總線的構(gòu)建。在數(shù)字電路中,邏輯輸出有兩個正常態(tài):低電平狀態(tài)(對應(yīng)邏輯0)和高電平狀態(tài)(對應(yīng)邏輯1);此外,電路還有不屬于0和1狀態(tài)的高組態(tài)(對應(yīng)于邏輯Z)。所謂高阻,即輸出端屬于浮空狀態(tài),只有很小的漏電流流動,其電平隨外部電平高低而定,門電平放棄對輸出電路的控制。或者可以理解為輸出與電路是斷開的。最基本的三態(tài)緩沖器的邏輯符號如圖2-10所示。
當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資源的作用。當然,可根據(jù)實際需求將38譯碼器擴展到更高級數(shù)上。
例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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-11所示。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖2-12所示
2.6.2 基本時序處理模塊
1.奇、偶數(shù)分頻電路
在數(shù)字邏輯電路設(shè)計中,分頻器是一種基本電路。通常用來對某個給定頻率進行分頻,以得到所需的頻率。
偶數(shù)倍分頻是最簡單的一種分頻模式,完全可通過計數(shù)器計數(shù)實現(xiàn)。如要進行N倍偶數(shù)分頻,那么可由待分頻的時鐘觸發(fā)計數(shù)器計數(shù),當計數(shù)器從0計數(shù)到N/2-1時,輸出時鐘進行翻轉(zhuǎn),并給計數(shù)器一個復(fù)位信號,使得下一個時鐘從零開始計數(shù),以此循環(huán)下去。這種方法可以實現(xiàn)任意的偶數(shù)分頻。例2-21給出的是一個16分頻電路,其它倍數(shù)的分頻電路可通過修改計數(shù)器的上限值得到。
例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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-13所示。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖2-14所示,從中可以看出例2-21成功實現(xiàn)了輸入時鐘的16分頻。
圖2-14 16分頻電路的仿真結(jié)果示意圖
奇數(shù)倍分頻有多種實現(xiàn)方法,下面介紹常用的錯位“異或”法的原理。如進行三分頻,通過待分頻時鐘上升沿觸發(fā)計數(shù)器進行模三計數(shù),當計數(shù)器計數(shù)到鄰近值進行兩次翻轉(zhuǎn)。比如在計數(shù)器計數(shù)到1時,輸出時鐘進行翻轉(zhuǎn),計數(shù)到2時再次進行翻轉(zhuǎn),即在鄰近的1和2時刻進行兩次翻轉(zhuǎn)。這樣實現(xiàn)的三分頻占空比為1/3或者2/3。如果要實現(xiàn)占空比為50%的三分頻時鐘,可以通過待分頻時鐘下降沿觸發(fā)計數(shù),和上升沿同樣的方法計數(shù)進行三分頻,然后將下降沿產(chǎn)生的三分頻時鐘和上升沿產(chǎn)生的時鐘進行相或運算,即可得到占空比為50%的三分頻時鐘。
這種錯位“異或”法可以推廣實現(xiàn)任意的奇數(shù)分頻:對于實現(xiàn)占空比為50%的N倍奇數(shù)分頻,首先進行上升沿觸發(fā)的模N計數(shù),計數(shù)到某一選定值時進行輸出時鐘翻轉(zhuǎn),然后經(jīng)過(N-1)/2再次進行翻轉(zhuǎn)得到一個占空比非50%奇數(shù)N分頻時鐘。再者同時進行下降沿觸發(fā)的模N計數(shù),到和上升沿觸發(fā)輸出時鐘翻轉(zhuǎn)選定值相同值時,進行輸出時鐘時鐘翻轉(zhuǎn),同樣經(jīng)過(N-1)/2時,輸出時鐘再次翻轉(zhuǎn)生成占空比非50%的奇數(shù)N分頻時鐘。兩個占空比非50%的N分頻時鐘相或運算,得到占空比為50%的奇數(shù)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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-15所示。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖2-16所示,可以看到輸出時鐘為占空比為50%的3分頻時鐘。
2.同步采樣模塊
在實際應(yīng)用中,外部輸入的異步信號需要經(jīng)過系統(tǒng)時鐘的同步化,且將輸入的異步信號整形成一個時鐘長的脈沖信號,如圖2-17所示。這里以例2-23來說明實現(xiàn)的方法。
例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
上述程序經(jīng)過綜合Synplify Pro后,其RTL級結(jié)構(gòu)如圖2-18所示。從結(jié)果上看,該電路非常簡單,但需要一定的時序邏輯能力才能真正理解該段程序。
在ModelSim 6.2b中完成仿真,其結(jié)果如圖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在時鐘周期內(nèi)出現(xiàn)抖動,也不會影響輸出結(jié)果,還是被整形成一個時鐘寬度。所以不管是長周期信號還是短周期信號,經(jīng)過同步采樣后,有效高電平寬度都等于時鐘周期。
3.同步狀態(tài)機的Verilog實現(xiàn)
狀態(tài)機一般包括組合邏輯和寄存器邏輯兩部分。組合電路用于狀態(tài)譯碼和產(chǎn)生輸出信號,寄存器用于存儲狀態(tài)。狀態(tài)機的下一個狀態(tài)及輸出不僅與輸入信號有關(guān),還與寄存器當前狀態(tài)有關(guān)。根據(jù)輸出信號產(chǎn)生方法的不同,狀態(tài)機可分為米里(Mealy)型和摩爾(Moore)型。前者的輸出是當前狀態(tài)和輸入信號的函數(shù),后者的輸出僅是當前狀態(tài)的函數(shù)。在硬件設(shè)計時,根據(jù)需要決定采用哪種狀態(tài)機。
狀態(tài)編碼又稱狀態(tài)分配。通常有多種編碼方法,編碼方案選擇得當,設(shè)計的電路可以簡單;反之,電路會占用過多的邏輯或速度降低。設(shè)計時,須綜合考慮電路復(fù)雜度和電路性能這兩個因素。下面主要介紹二進制編碼、格雷編碼和獨熱碼。
二進制編碼和格雷碼都是壓縮狀態(tài)編碼。二進制編碼的優(yōu)點是使用的狀態(tài)向量最少,但從一個狀態(tài)轉(zhuǎn)換到相鄰狀態(tài)時,可能有多個比特位發(fā)生變化,瞬變次數(shù)多,易產(chǎn)生毛刺。格雷編碼在相鄰狀態(tài)的轉(zhuǎn)換中,每次只有1個比特位發(fā)生變化,雖減少了產(chǎn)生毛刺和一些暫態(tài)的可能,但不適用于有很多狀態(tài)跳轉(zhuǎn)的情況。
獨熱碼是指對任意給定的狀態(tài),狀態(tài)向量中只有1位為1,其余位都為0。n狀態(tài)的狀態(tài)機需要n個觸發(fā)器。這種狀態(tài)機的速度與狀態(tài)的數(shù)量無關(guān),僅取決于到某特定狀態(tài)的轉(zhuǎn)移數(shù)量,速度很快。當狀態(tài)機的狀態(tài)增加時,如果使用二進制編碼,那么狀態(tài)機速度會明顯下降。而采用獨熱碼,雖然多用了觸發(fā)器,但由于狀態(tài)譯碼簡單,節(jié)省和簡化了組合邏輯電路。獨熱編碼還具有設(shè)計簡單、修改靈活、易于綜合和調(diào)試等優(yōu)點。對于寄存器數(shù)量多、而門邏輯相對缺乏的FPGA器件,采用獨熱編碼可以有效提高電路的速度和可靠性,也有利于提高器件資源的利用率。獨熱編碼有很多無效狀態(tài),應(yīng)該確保狀態(tài)機一旦進入無效狀態(tài)時,可以立即跳轉(zhuǎn)到確定的已知狀態(tài)。
用Verilog 語言描述有限狀態(tài)機可使用多種風(fēng)格,不同的風(fēng)格會極大地影響電路性能。通常有3種描述方式:單always塊、雙always塊和三always塊。
單always塊把組合邏輯和時序邏輯用同一個時序always塊描述,其輸出是寄存器輸出,無毛刺。但是這種方式會產(chǎn)生多余的觸發(fā)器,代碼難于修改和調(diào)試,應(yīng)該盡量避免使用。
雙always塊大多用于描述Mealy狀態(tài)機和組合輸出的Moore狀態(tài)機,時序always塊描述當前狀態(tài)邏輯,組合邏輯always塊描述次態(tài)邏輯并給輸出賦值。這種方式結(jié)構(gòu)清晰,綜合后的面積和時間性能好。但組合邏輯輸出往往會有毛刺,當輸出向量作為時鐘信號時,這些毛刺會對電路產(chǎn)生致命的影響。
三always塊大多用于同步Mealy狀態(tài)機,兩個時序always塊分別用來描述現(xiàn)態(tài)邏輯和對輸出賦值,組合always塊用于產(chǎn)生下一狀態(tài)。這種方式的狀態(tài)機也是寄存器輸出,輸出無毛刺,并且代碼比單always塊清晰易讀,但是面積大于雙always塊。隨著芯片資源和速度的提高,目前這種方式得到了廣泛應(yīng)用。
下面以三always塊模塊給出狀態(tài)機的Verilog模板。
// 構(gòu)成狀態(tài)跳轉(zhuǎn)環(huán)
always @(posedge clk or negedge rst_n)
current_state <= next_state;
// 完成狀態(tài)機的內(nè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)硬件設(shè)計,必須寫出可以綜合的程序。通常,綜合的原則為:
三、其他
鑒相:
濾波: