[数字IC手撕verilog]时钟无毛刺切换

module clk_glitch_free
(
input clk1,
input clk2,
input rst_n,
input en,
output clk_out
);
reg clk1_q1, clk1_q2;
reg clk2_q1, clk2_q2;
always @(posedge clk1 or negedge rst_n)begin
if(!rst_n)
clk1_q1 <= 1'b0;
else
clk1_q1 <= en & ~clk2_q2;
end
always @(negedge clk1 or rst_n)begin
if(!rst_n)
clk1_q2 <= 1'b0;
else
clk1_q2 <= clk1_q1;
end
always @(posedge clk2 or negedge rst_n)begin
if(!rst_n)
clk2_q1 <= 1'b0;
else
clk1_q1 <= ~en & ~clk1_q2;
end
always @(negedge clk2 or rst_n)begin
if(!rst_n)
clk2_q2 <= 1'b0;
else
clk2_q2 <= clk1_q1;
end
assign clk_out = (clk1 & clk1_q2) || (clk2 & clk2_q2);
endmodule
testbench
`timescale 1ns/1ps
module tb;
reg clk1, clk2;
reg en, rstn;
wire clk_out;
initial begin
clk1 = 1'b0;
#5 clk1 = 1'b1;
forever clk1 = ~clk1;
end
initial begin
clk2 = 1'b0;
#12 clk2 = 1'b1;
forever clk2 = ~clk2;
end
initial begin
rstn = 1'b0;
#25 rstn = 1'b1;
end
initial begin
en = 1'b0;
#80 en = 1'b1;
#120 en = 1'b0;
#60 en = 1'b1;
#50 $finish;
end
clk_glitch_free inst
(clk1, clk2, rstn, clk_out);
endmodule