最后的DEMO直觀的描述了使能時鐘的使用,可以一看
門控時鐘 時鐘使能電路是同步設計的重要基本電路,在很多設計中,雖然內部不同模塊的處理速度不同,但是由于這些時鐘是同源的,可以將它們轉化為單一的時鐘電路處理。在FPGA的設計中,分頻時鐘和源時鐘的skew不容易控制,難以保證分頻時鐘和源時鐘同相。故此推薦采用使用時鐘使能的方法,通過使用時鐘使能可以避免時鐘“滿天飛”的情況,進而避免了不必要的亞穩態發生,在降低設計復雜度的同時也提高了設計的可靠性。 門控時鐘 Verilog示例代碼: input wr_n; //寫使能信號,低有效 input cs_n; //片選信號,低有效 input[7:0] db; //輸入數據總線
output db_r; //鎖存輸出
reg db_r; //輸入數據寄存器 wire d_clk; //門控時鐘信號
assign d_clk = wr_n || cs_n;
always @ (posedge d_clk) //門控時鐘上升沿 db_r <= db; //鎖存輸入數據
RTL Viewer:

組合邏輯中多用門控時鐘,一般驅動門控時鐘的邏輯都是只包含一個與門(或門)。如果有其它的附加邏輯,容易因競爭產生不希望的毛刺。
使能時鐘
Verilog示例代碼: input clk; //50MHz時鐘信號 input wr_n; //寫使能信號,低有效 input cs_n; //片選信號,低有效 input[7:0] db; //數據總線
output db_r; reg db_r; //輸入數據寄存器 wire en; //使能信號
assign en = ~wr_n && ~cs_n;
always @ (posedge clk) //全局時鐘上升沿 if(en) //使能鎖存輸入 db_r <= db; //鎖存輸入數據
RTL Viewer:
使能時鐘這要是用于時序邏輯中,比門控時鐘要來的穩定。 上面只是一個舉例,實際上它們實現的功能上還是有一點差別的。門控時鐘一例中是能夠比較準確的在wr_n的上升沿鎖存數據的。而使能時鐘一例中在wr_n有效期間的每個時鐘周期都會鎖存輸入數據,最后寫入結束后鎖存寄存器里的數據是wr_n上升前的0-T(T=1/clk)時間內鎖存的數據。因為是個例子,也就不詳細說,具體情況具體分析。
在某系統中,前級數據輸入位寬為8,而后級的數據輸出位寬32,我們需要將8bit的數據轉換成32bit的數據,因此后級處理的時鐘頻率為前級的1/4,若不使用時鐘時能,則就要將前級時鐘進行4分頻來作為后級處理的時鐘,這種設計方法會引入新的時鐘域,為了避免這種情況,我們采用了時鐘時能的方法來減少設計的復雜度。
module gray
(
input clk,
input rst_n,
input [7:0] data_in,
output reg [31:0] data_out,
output reg clk1x_en
);
reg [1:0] cnt;
reg [31:0] shift_reg;
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
cnt <= 2'b0;
else
cnt <= cnt +1'b1;
end
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
clk1x_en <= 1'b0;
else if(cnt ==2'b01)
clk1x_en <= 1'b1;
else
clk1x_en <= 1'b0;
end
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
shift_reg <= 32'b0;
else
shift_reg <= {shift_reg[23:0],data_in};
end
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
data_out<= 32'b0;
else if(clk1x_en==1'b1)//僅在clk1x_en為1時才將shift_reg的值賦給data_out
data_out<=shift_reg;
end
endmodule
|