一种无毛刺的时间切换解决方案,某发笔试题。
Code:
module glitch_free_clock_switching(
input clk_0,
input clk_1,
input rst_n,
input select,
output o_clk
);
//=================defination
wire s_0, s0;
wire s_1, s1;
reg s_0r, s_0rn;
reg s_1r, s_1rn;
//=================output
assign s_0 = select & (~s_1rn);
assign s_1 = (~select) & (~s_0rn);
always@(posedge clk_0 or negedge rst_n)begin
if(!rst_n) s_0r <= 1'b0;
else s_0r <= s_0;
end
always@(posedge clk_1 or negedge rst_n)begin
if(!rst_n) s_1r <= 1'b0;
else s_1r <= s_1;
end
always@(negedge clk_0 or negedge rst_n)begin
if(!rst_n) s_0rn <= 1'b0;
else s_0rn <= s_0r;
end
always@(negedge clk_1 or negedge rst_n)begin
if(!rst_n) s_1rn <= 1'b0;
else s_1rn <= s_1r;
end
assign s0 = clk_0 & s_0rn;
assign s1 = clk_1 & s_1rn;
assign o_clk = s0 | s1;
endmodule
Tsetbench:
时钟相移的clock写法
module tb_glitch_free_clock_switching();
//===================parameter
parameter SHIFT = 2;
parameter PERIOD0 = 10 / 2;
parameter PERIOD1 = 16 / 2;
parameter WIDTH = 8;
parameter WIDTH_dout = 16;
//===================defination
reg clk_0, clk_1, rst_n, select;
wire clk_1s;
//===================output
initial begin
clk_0 = 0;
clk_1 = 0;
rst_n = 0;
#20 rst_n = 1;
#1000 $finish;
end
initial begin
select = 0;
#100 select = 1;
#210 select = 0;
#534 select = 1;
end
always #PERIOD0 clk_0 = ~clk_0;
always #PERIOD1 clk_1 = ~clk_1;
assign #SHIFT clk_1s = clk_1;
glitch_free_clock_switching u_switching
(
.clk_0(clk_0),
.clk_1(clk_1s),
.rst_n(rst_n),
.select(select),
.o_clk(o_clk)
);
`ifdef FSDB
initial begin
$fsdbDumpfile("tb_glitch_free_clock_switching.fsdb");
$fsdbDumpvars;
$fsdbDumpMDA();
end
`endif
endmodule
VCS:
- 仿真结果说明:当select异步变化的时候,原时钟经过一个上升沿(同步select)一个下降沿(等时钟完全结束)关闭,切换时钟经过一个上升沿一个下降沿开始作用。
Schematic: