用Verilog实现glitch free时钟切换电路,输入clka,clkb,rst_n,sel,sel为1输出clka,sel为0输出clkb(clka和clkb为不同源时钟):
RTL代码:
module glitch_clk(
input clka,
input clkb,
input rst_n,
input sel,
output outclk
);
reg sel_a;
reg sel_a_r;
reg sel_b;
reg sel_b_r;
always@(posedge clka or negedge rst_n)//上升沿有效,降低亚稳态发生的概率
if(!rst_n)
sel_a_r <= 1'b0;
else
sel_a_r <= ~sel_b && sel;
always@(negedge clka or negedge rst_n)//下降沿有效,防止毛刺
if(!rst_n)
sel_a <= 1'b0;
else
sel_a <= sel_a_r;
always@(posedge clkb or negedge rst_n)
if(!rst_n)
sel_b_r <= 1'b0;
else
sel_b_r <= ~sel_a && ~sel;
always@(negedge clkb or negedge rst_n)
if(!rst_n)
sel_b <= 1'b0;
else
sel_b <= sel_b_r;
assign outclk = (clka & sel_a)|(clkb & sel_b);
endmodule
仿真:
`timescale 1ns / 1ps
module glitch_clk_tb;
// Inputs
reg clka;
reg clkb;
reg rst_n;
reg sel;
// Outputs
wire outclk;
// Instantiate the Unit Under Test (UUT)
glitch_clk uut (
.clka(clka),
.clkb(clkb),
.rst_n(rst_n),
.sel(sel),
.outclk(outclk)
);
initial clka = 0;
always#10 clka = ~clka;
initial clkb = 0;
always#25 clkb = ~clkb;
initial begin
// Initialize Inputs
rst_n = 0;
sel = 0;
// Wait 100 ns for global reset to finish
#105;
// Add stimulus here
rst_n = 1;
#302;
sel = 1;
#508;
sel = 0;
#406;
$stop;
end
endmodule