Verilog -- 無glitch時鍾切換電路
題目:用Verilog實現glitch free時鍾切換電路。輸入sel,clka,clkb,sel為1輸出clka,sel為0輸出clkb
第一種
純組合邏輯

module clk_select1(
input clk1,
input clk2,
input rst_n,
input sel,
output clk_out
);
assign clk_out = sel?clk1:clk2;
endmodule
缺點:會有毛刺
第二種
在時鍾的下降沿寄存選擇信號(SELECT)可確保在任一時鍾處於高電平時輸出端不會發生變化,從而防止斬波輸出時鍾(意思是下降沿寄存,可以保證下降沿到來之前輸出端保持不變,這樣就不會斬斷當前時鍾了)
缺點:當sel信號出現再clk的下降沿,或者兩個寄存器的下降沿重合的地方可能會產生亞穩態
代碼:
module clk_select2(
input clk1,
input clk2,
input rst_n,
input sel,
output clk_out
);
reg ff1;
reg ff2;
always @(negedge clk1 or negedge rst_n) begin
if(!rst_n) ff1 <= 1'b0;
else begin
ff1 <= ~ff2 & sel;
end
end
always @(negedge clk2 or negedge rst_n) begin
if(!rst_n) ff2 <= 1'b0;
else begin
ff2 <= ~ff1 & ~sel;
end
end
assign clk_out = (ff1 & clk1) | (ff2 & clk2);
endmodule
對於第一種會有毛刺,而第二種則不會,但是當clk1和clk2是純異步的情況下(有skew) :
第三種
第二種可能會有亞穩態,所以可以加兩級寄存器緩沖。
代碼如下:
`timescale 1ns/1ps
module clk_select3(
input clk1,
input clk2,
input rst_n,
input sel,
output clk_out
);
reg ff1,ff1_d;
reg ff2,ff2_d;
always @(negedge clk1 or negedge rst_n) begin
if(!rst_n) {ff1,ff1_d} <= 2'b00;
else begin
ff1_d <= ~ff2 & sel;
ff1 <= ff1_d;
end
end
always @(negedge clk2 or negedge rst_n) begin
if(!rst_n) {ff2,ff2_d} <= 2'b00;
else begin
ff2_d <= ~ff1 & ~sel;
ff2 <= ff2_d;
end
end
assign clk_out = (ff1 & clk1) | (ff2 & clk2);
endmodule
testbench:
`timescale 1ns/1ps
module clk_select_tb;
reg clk1;
reg clk2;
reg rst_n;
reg sel;
wire clk_comb;
wire clk_reg1;
wire clk_reg2;
initial begin
clk1 = 1;
clk2 = 1;
fork
forever #1 clk1 = ~clk1;
begin
#1.2;
clk2 = 1;
forever #5 clk2 = ~clk2;
end
join_none
rst_n = 1;
sel = 0;
#2 rst_n = 0;
#10 rst_n = 1;
#21.7 sel = 1;
end
initial begin
$fsdbDumpvars();
$fsdbDumpMDA();
$dumpvars();
#100 $finish;
end
clk_select1 U_CLK_SEL_0(
.clk1 ( clk1 ),
.clk2 ( clk2 ),
.clk_out ( clk_comb ),
.sel ( sel ),
.rst_n ( rst_n )
);
clk_select2 U_CLK_SEL_1(
.clk1 ( clk1 ),
.clk2 ( clk2 ),
.clk_out ( clk_reg1 ),
.sel ( sel ),
.rst_n ( rst_n )
);
clk_select3 U_CLK_SEL_2(
.clk1 ( clk1 ),
.clk2 ( clk2 ),
.clk_out ( clk_reg2 ),
.sel ( sel ),
.rst_n ( rst_n )
);
endmodule
缺點: 輸出會有一個周期延時(較長的那個周期)
仿真波形:
