无毛刺时钟切换电路?相关时钟&不相关时钟
设计一个无毛刺时钟切换电路?Glitch Free Clock
常规的时钟切换电路,利用一个选择器实现,容易产生毛刺。
常规时钟切换电路设计代码&激励代码&仿真波形
module glitch_free( input clk_0 , input clk_1 , input select , output clk_out ); assign clk_out=(select&clk_1)|(~select&clk_0); endmodule
`timescale 1ns/1ns module tb_glitch_free(); reg clk_0 ; reg clk_1 ; reg select ; wire clk_out ; initial begin clk_0<=1'b0; clk_1<=1'b0; select<=1'b0; #200 select<=1'b1; #305 select<=1'b0; #500 select<=1'b1; #125 select<=1'b0; #30 select<=1'b1; #65 select<=1'b0; #70 select<=1'b1; #300 select<=1'b0; end always #10 clk_0<=~clk_0 ; always #8 clk_1<=~clk_1 ; glitch_free glitch_free_inst( .clk_0 (clk_0 ) , .clk_1 (clk_1 ) , .select (select ) , .clk_out (clk_out ) ); endmodule
相关时钟的无毛刺处理:在每个时钟源选择的路径上,各插入一个下降沿有效的D触发器,来防止毛刺的产生。
为什么选择下降沿:
在时钟的每个下降沿寄存选择控制信号 SELECT,并且只有在其他时钟的选择被释放后(无效后)才会使能新的时钟选择,这样对输出毛刺问题进行很好的解决。
在时钟的下降沿处寄存选择控制信号,保证了控制信号不会在 2 个时钟源的高电平处进行跳变,这样就防止对输出时钟进行截断(截断导致毛刺)。
在这个电路中有 3 条时序路径需要特别考虑:
(1)SELECT 控制信号到任意一个下降沿有效的触发器 ;
(2)DFF0 的输出到 DFF1 的输入;
(3)DFF1 的输出到 DFF0 的输入。
如果这三条路径中的任何一条路径上的信号与目标触发器时钟的捕获边缘同时发生变化,则该寄存器的输出很可能变为亚稳态,这意味着它可能会进入理想的0和1两者之间的状态。
相关时钟的无毛刺处理设计代码&激励代码&仿真波形
module glitch_free( input clk_0 , input clk_1 , input select , output clk_out ); reg ff_00 ; reg ff_01 ; reg ff_10 ; reg ff_11 ; wire sel_0 ; wire sel_1 ; wire clk_out_0 ; wire clk_out_1 ; assign sel_1 = select&ff_00; assign sel_0 = (~select)&ff_10; always@(negedge clk_0) begin ff_00<=~sel_0; ff_01<=sel_0; end always@(negedge clk_1) begin ff_10<=~sel_1; ff_11<=sel_1; end assign clk_out_0=clk_0&ff_01; assign clk_out_1=clk_1&ff_11; assign clk_out=clk_out_0 | clk_out_1 ; endmodule
`timescale 1ns/1ns module tb_glitch_free(); reg clk_0 ; reg clk_1 ; reg select ; wire clk_out ; initial begin clk_0<=1'b0; clk_1<=1'b0; select<=1'b0; #200 select<=1'b1; #305 select<=1'b0; #500 select<=1'b1; #125 select<=1'b0; #30 select<=1'b1; #65 select<=1'b0; #70 select<=1'b1; #300 select<=1'b0; end always #10 clk_0<=~clk_0 ; always #5 clk_1<=~clk_1 ; glitch_free glitch_free_inst( .clk_0 (clk_0 ) , .clk_1 (clk_1 ) , .select (select ) , .clk_out (clk_out ) ); endmodule
不相关时钟的无毛刺处理:对每个时钟源路径上,各增加一个该时钟源上升沿驱动的触发器来避免亚稳态,时钟源路径上增加的上升沿有效的触发器,与现有的下降沿有效的触发器一起,用于减少 SELECT 或者异步反馈信号导致的潜在的亚稳态的概率。即可以这样理解 上升沿驱动的触发器减少亚稳态,下降沿驱动的触发器来防止毛刺产生。
不相关时钟的无毛刺处理设计代码&激励代码&仿真波形
module glitch_free( input clk_0 , input clk_1 , input select , output clk_out ); reg ff_00 ; reg ff_01 ; reg ff_10 ; reg ff_11 ; wire sel_0 ; wire sel_1 ; wire clk_out_0 ; wire clk_out_1 ; assign sel_1 = select&(~ff_11); assign sel_0 = (~select)&(~ff_01); always@(posedge clk_0) begin ff_00<=sel_1; end always@(negedge clk_0) begin ff_01<=ff_00; end always@(posedge clk_1) begin ff_10<=sel_0; end always@(negedge clk_1) begin ff_11<=ff_10; end assign clk_out_0=clk_0&ff_01; assign clk_out_1=clk_1&ff_11; assign clk_out=clk_out_0 | clk_out_1 ; endmodule
`timescale 1ns/1ns module tb_glitch_free(); reg clk_0 ; reg clk_1 ; reg select ; wire clk_out ; initial begin clk_0<=1'b0; clk_1<=1'b0; select<=1'b0; #200 select<=1'b1; #305 select<=1'b0; #500 select<=1'b1; #125 select<=1'b0; #30 select<=1'b1; #65 select<=1'b0; #70 select<=1'b1; #300 select<=1'b0; end always #3 clk_0<=~clk_0 ; always #5 clk_1<=~clk_1 ; glitch_free glitch_free_inst( .clk_0 (clk_0 ) , .clk_1 (clk_1 ) , .select (select ) , .clk_out (clk_out ) ); endmodule
若有不对的地方,敬请指正,万分感谢。
参考资料:1、Techniques For Glitch Free Clock Switching (MUX) - EE Times
2、(117条消息) verilog 基础设计11-glitch free 无毛刺的时钟切换_无关时钟无毛刺切换verilog_瞅什么瞅的博客-CSDN博客
3、(117条消息) 【Verilog HDL 训练】第 14 天(glitch-free的两个时钟切换电路)_时钟切换电路verilog_李锐博恩的博客-CSDN博客
4、FPGA/数字IC秋招笔试面试031——Glitch free 无毛刺时钟切换电路、时钟无缝切换、时钟无毛刺切换技术【2022届】 - 知乎 (zhihu.com)