参考博文:https://blog.csdn.net/u014070258/article/details/90052426

  在设计多时钟系统中,需要切换时钟源,这两个时钟可能是没有关联的(相位、频率),或者他们为倍数关系。这两种情况都有可能在开关时产生毛刺(glitch),而系统上的毛刺对系统来说是危险的,他可能能够被一些寄存器捕获为触发边沿,而其他寄存器忽略此毛刺。  

  时钟切换的简单实现

   在这种情况下就会出现毛刺,产生这种问题的根本原因是切换控制信号相对于时钟信号可以在任何时间里发生改变,本质是切换信号为异步信号。 任何时钟的高电平状态下的切换都需要避免。当两个输入时钟之间是倍数关系时,插入下降沿触发触发器确保切换只发生在时钟为低电平时候,引入输出反馈确保另外一路的时钟为低电平时候发生切换,

 

  上述电路的缺点 没有解决异步的问题,有可能会出现亚稳态问题,下面电路第一级通过锁定数据来帮助稳定数据,然后将数据传递到下一级

 

 

   ALTER推荐的时钟切换电路图

 

/***************************************************

*无毛刺切换时钟,要点

*    1、clkx_synx 复位后为0

*    2、在高电平状态下不切换时钟

*    3、同步寄存器为posedge 触发

*    4、最后一级为 negedge 触发,确保切换发生在时钟为低电平

****************************************************/

module clk_mux(

input rst,
input clk1,
input clk2,
input sel,

output m_clk
);

reg clk1_syn1;
reg clk1_syn2;

reg clk2_syn1;
reg clk2_syn2;

/*同步寄存器*/
always @(posedge clk1 or negedge rst)
if(!rst)
clk1_syn1 <= 1\’b0;
else
clk1_syn1 <= sel & (~clk2_syn2);

always @(negedge clk1 or negedge rst)
if(!rst)
clk1_syn2 <= 1\’b0;
else
clk1_syn2 <= clk1_syn1;

/*同步寄存器*/
always @(posedge clk2 or negedge rst)
if(!rst)
clk2_syn1 <= 1\’b0;
else
clk2_syn1 <= (~sel) & (~clk1_syn2);

always @(negedge clk2 or negedge rst)
if(!rst)
clk2_syn2 <= 1\’b0;
else
clk2_syn2 <= clk2_syn1;

assign m_clk = (clk1 & clk1_syn2) | (clk2 & clk2_syn2);

endmodule
 

版权声明:本文为gujiangtaoFuture原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/gujiangtaoFuture/articles/12535140.html