时钟无毛刺切换

20220812更新:

图好像画错了,中间那个与门的输入其中一个是clk2,而不是clk3.

今天来讲一下时钟无毛刺切换技术。

顾名思义,时钟的无毛刺切换技术,其要点在于消除切换时可能会产生的毛刺

图片

当选择信号select改变时,旧时钟和新时钟只要有一个处于高电平,那么原理上就有产生毛刺的风险。

①旧时钟为高电平,新时钟为低电平,可能会产生负脉冲,如上图所示。

②旧时钟为低电平,新时钟为高电平,可能会产生正脉冲,如下图(图太丑了,见谅) 

 ③新旧时钟都为高电平,可能出现正毛刺,这个大家可以想一下为什么。

因此新旧时钟都为低电平时,为最佳的切换时间。但是当时钟之间的相位关系不确定时,是无法依靠确定性的电路设计在最佳切换时间是完成切换的。

上图所示为 常见的无毛刺切换电路,ck_sel信号经过同步后给到一个下降沿触发的寄存器,其输出与时钟信号经过一个与门,得到可用时钟信号,所有的可用时钟信号最后通过一个或门输出,

ck_sel信号是以下两种信号通过与门得到:

①选通信号经过译码后的本时钟选通信号。

②其他时钟的下降沿出发寄存器的非端。

电路的特点:

①当某个时钟被选通时,其他时钟不可能被选通。

②所有的选通信号都是下降沿变化,保证了选通信号改变时旧时钟是低电平

③旧时钟的选通信号拉低的时候,其他时钟的选通信号都是低电平,且隔一段时间才会拉高,

④时钟的切换步骤是:最初的选通信号改变->旧时钟的选通信号被拉低->新时钟的选通信号被拉高。

因此新旧时钟切换的中间,存在一段时间,在这段时间内,没有任何时钟被选通。

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/07/25 11:19:22
// Design Name: 
// Module Name: glitch_free
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module glitch_free(
    input clk1,
    input clk2,
    input clk3,
    input rstn,
    input [1:0] sel,
    input clk_out
    );
    
    wire sel1,sel2,sel3;
    wire ck_sel1,ck_sel2,ck_sel3;
    wire clk1_or,clk2_or,clk3_or;
    reg ck_sel1_r1,ck_sel1_r2,ck_sel1_neg;
    reg ck_sel2_r1,ck_sel2_r2,ck_sel2_neg;
    reg ck_sel3_r1,ck_sel3_r2,ck_sel3_neg;
    
    
   
    assign sel1=(sel==2'b01);
    assign sel2=(sel==2'b10);
    assign sel3=(sel==2'b11);
    
    assign ck_sel1=sel1&(~ck_sel2_neg)&(~ck_sel3_neg);
    assign ck_sel2=sel2&(~ck_sel1_neg)&(~ck_sel3_neg);
    assign ck_sel3=sel3&(~ck_sel1_neg)&(~ck_sel2_neg);
    
    assign clk1_or = clk1&ck_sel1_neg;
    assign clk2_or = clk2&ck_sel2_neg;
    assign clk3_or = clk3&ck_sel3_neg;
    
    assign clk_out = clk1_or|clk2_or|clk3_or;
    
    always @ (posedge clk1 or negedge rstn)begin
        if (!rstn) 
            {ck_sel1_r1,ck_sel1_r2} <= 2'b000;
        else 
            {ck_sel1_r2,ck_sel1_r1} <= {ck_sel1_r1,ck_sel1};
    end
    
    always @ (negedge clk1 or negedge rstn)begin
        if (!rstn)
            ck_sel1_neg <= 1'b0;
        else
            ck_sel1_neg <= ck_sel1_r2;
    end
    

    always @ (posedge clk2 or negedge rstn)begin
        if (!rstn) 
            {ck_sel2_r1,ck_sel2_r2} <= 2'b000;
        else 
            {ck_sel2_r2,ck_sel2_r1} <= {ck_sel2_r1,ck_sel2};
    end
    
    always @ (negedge clk2 or negedge rstn)begin
        if (!rstn)
            ck_sel2_neg <= 1'b0;
        else
            ck_sel2_neg <= ck_sel2_r2;
    end


    always @ (posedge clk3 or negedge rstn)begin
        if (!rstn) 
            {ck_sel3_r1,ck_sel3_r2} <= 2'b000;
        else 
            {ck_sel3_r2,ck_sel3_r1} <= {ck_sel3_r1,ck_sel3};
    end
    
    always @ (negedge clk3 or negedge rstn)begin
        if (!rstn)
            ck_sel3_neg <= 1'b0;
        else
            ck_sel3_neg <= ck_sel3_r2;
    end

    

endmodule

仿真结果

未注明的参考文章在此处列出:

(41条消息) Glitch free 无毛刺时钟切换电路、时钟无缝切换、时钟无毛刺切换技术_Cheeky_man的博客-CSDN博客_时钟无缝切换

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Verilog 中实现无毛刺切换的关键是通过合适的时序处理来保证在切换时钟时不会出现意外的冲突。以下是一个示例代码,演示如何在两个时钟之间实现无毛刺切换: ```verilog module clock_switch ( input wire clk1, input wire clk2, input wire switch_trigger, output wire switched_clk ); reg switched_clk_reg; reg switched_clk_next; always @(posedge clk1 or posedge clk2 or posedge switch_trigger) begin if (switch_trigger) begin if (clk1) begin switched_clk_next <= 1'b0; end else begin switched_clk_next <= 1'b1; end end else if (clk1) begin switched_clk_next <= 1'b1; end else begin switched_clk_next <= 1'b0; end end always @(posedge clk1 or posedge clk2) begin switched_clk_reg <= switched_clk_next; end assign switched_clk = switched_clk_reg; endmodule ``` 在这个示例代码中,我们有两个输入时钟 `clk1` 和 `clk2`,一个触发切换的输入信号 `switch_trigger`,以及一个输出时钟 `switched_clk`。 使用两个 `always` 块来处理时钟切换逻辑。第一个 `always` 块在 `clk1`、`clk2` 和 `switch_trigger` 的上升沿时执行。当 `switch_trigger` 触发时,根据当前的 `clk1` 的状态来选择输出时钟,如果 `clk1` 为高电平,则输出时钟 `switched_clk` 为低电平,否则为高电平。如果没有触发切换,则根据 `clk1` 的状态来决定输出时钟。 第二个 `always` 块在 `clk1` 和 `clk2` 的上升沿时执行,并将 `switched_clk_next` 的值赋给 `switched_clk_reg`,用于时钟输出。 最后,使用 `assign` 语句将 `switched_clk_reg` 赋值给 `switched_clk` 输出。 需要注意的是,这个示例代码只是演示了一个简单的时钟切换逻辑,实际应用中可能需要更多的时序处理和输入检查来确保正确的时钟切换。同时,请根据具体的设计要求和目标平台的特性进行适当的优化和约束设置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值