glitch fress clk en设计:

电路图和波形如上图所示,RTL实现如下:
verilog描述也很简单
always @ (clk_in or EN) begin
if ( ! clk_in)
clkEn <= EN;
end
assign gated_clk = clkEn & clk_in;
glitch free clkmux设计:
有了上面clk gate的思想,下面介绍glitch free clkmux 的设计思路:

如上图电路所示,我们只需要用RTL来实现这个电路即可:
module glitch_free_ckmux
(
input rstn ,
input [ 1:0] i_clk ,
input sel ,
output o_clk
);
wire [1:0] src_clk_lb, clk_en ;
reg [1:0] n_en_reg ;
reg [1:0] n_en_reg_dly ;
wire [1:0] sync_clken_out ;
wire [1:0] src_clk_inv ;
wire [1:0] out_clk_and ;
genvar index;
generate for(index=0;index<2;index=index+1)
assign src_clk_lb[index] = i_clk[index];
assign src_clk_inv[index] = i_clk[index];
//sync 三拍
stsoc_sync_l3 sync_clk_en (
.ck (src_clk_lb[0]),
.clb (rstn),
.d (clk_en[0]),
.o (sync_clken_out[0])
);
//sync 三拍
stsoc_sync_l3 sync_clk_en (
.ck (src_clk_lb[1]),
.clb (rstn),
.d (clk_en[1]),
.o (sync_clken_out[1])
);
always @(posedge src_clk_inv[index] or negedge rstn)
if(!rstn)
begin
n_en_reg[0] <= 1'b1 ;
n_en_reg_dly[0] <= 1'b1 ;
n_en_reg[1] <= 1'b0 ;
n_en_reg_dly[1] <= 1'b0 ;
end
else
begin
n_en_reg[index] <= sync_clken_out[index] ;
n_en_reg_dly[index] <= n_en_reg[index] ;
end
endgenerate
assign clk_en[0] = ~sel & (!n_en_reg_dly[1]) ;
assign clk_en[1] = sel & (!n_en_reg_dly[0]) ;
//and gate
assign out_clk_and[0] = n_en_reg[0] & i_clk[0];
assign out_clk_and[1] = n_en_reg[1] & i_clk[1];
//or gate
assign o_clk = out_clk_and[0] | out_clk_and[1];
endmodule
参考文档:面试题分析 -- 时钟切换