当前位置: 首页 > article >正文

数字IC前端学习笔记:时钟切换电路

相关阅读

数字IC前端icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12173698.html?spm=1001.2014.3001.5482


        有些时候我们需要在系统运行时切换系统时钟,最简单的方法就是使用一个MUX(数据选择器)选择输出的时钟,如下代码片所示。但这样做会导致毛刺的产生,这可能会导致寄存器的输出产生亚稳态。由于时钟在一个系统内是如此的重要,这种亚稳态可能会使整个系统宕机。一个简单的使用数据选择器的时钟切换电路如下图1所示,时钟切换时的毛刺如图2所示。

module clock_switch(input clk_1, clk_2, select, output reg clk_out);
    always@(*) begin
        if(select == 1'b1)
            clk_out = clk_1;
        else
            clk_out = clk_2;
    end        
endmodule

图1 简单的数据选择器

图2 有毛刺的波形

        一种不会产生毛刺的时钟切换电路如下图3所示。该电路的输出为两个时钟门控输出的与,上半部分电路控制时钟clk_A,当门控信号a2i_2为1时门控关闭时钟clk_A,当门控信号a2i_2为0时门控打开时钟clk_A。下半部分电路控制时钟clk_B,当门控信号a4i_2为1时门控关闭时钟clk_B,当门控信号a4i_2为0时门控打开时钟clk_B。控制信号sel用于选择clk_A还是clk_B,当sel为0时a3o输出0,由于sel和a3i_2信号都不是clk_B时钟域的信号,因此这个输出需要经过clk_B时钟域的两级同步器得到a3o_sync信号,最后a3o_sync信号通过clk_B的下降沿采样得到a4i_2和!a4i_2,a4i_2用于关闭clk_B,而!a4i_2用于拉高a1o,从而最后将a2i_2拉高,即打开时钟clk_A(注意到对于a1o,即使sel为0,a1i_1为1,也不会立刻拉高,因为!a4i_2仍然为0),对sel为1的分析与上面类似,在此不详述。可以看到这种结构在时钟切换的过程中,首先关闭正在运行的时钟(此时没有时钟输出,输出恒为0),然后再开启另一个时钟,且这个关闭和开启的动作都是由本时钟所同步的行为,即clk_A负责关闭和开启clk_A,clk_B负责关闭和开启clk_B,这样就在一定程度上避免了毛刺的产生。S3和S6这两个触发器需要下降沿触发,这是为了在关闭和打开时钟时不产生毛刺,因为寄存器S3和S6的输出有一定延迟。如果使用上升沿触发,此时时钟信号为高电平,但门控信号a2i_2和a4i_2需要延迟一段时间才会拉高或拉低,此时会在a20和a4o产生毛刺,下降沿触发则不会有这个问题,因为时钟信号为低,这保证了a20和a4o一定为低,如图4和图5所示。但值得注意的是,这在无形中对时钟的占空比提出了要求,即占空比不能太高,最好为50%左右,否则还是会导致输出出现毛刺(在S3,S6延迟较大时)。图中的B2、B3、B4、B5实际综合后可能不存在,因为有专门的下降沿触发的寄存器,同时寄存器也有取反输出端。

图3 无毛刺的时钟切换电路

图4 使用上升沿触发出现毛刺

图4 使用下升沿触发不出现毛刺

        图5是没有毛刺的切换电路的波形图,可以看到切换有一定延迟但不会出现毛刺。

图5 没有毛刺的波形

        下面是以上电路的Verilog描述,在这里面要注意S3和S6的时钟触发沿。

module clock_switch(input clk_1, clk_2, select, rst_n1, rst_n2, output clk_out);  
//上半部分时钟控制的逻辑  
    wire a1i_1, a1o, a2o;
    reg a1o_r, a1o_syn, a2i_2, a4i_2;
    assign a1i_1 = !select;
    assign a1o = a1i_1 & !a4i_2;

    always@(posedge clk_1 or negedge rst_n1)begin //打两拍同步
        if(!rst_n1)begin
            a1o_r <= 0;
            a1o_syn <= 0;
        end
        else begin
            a1o_r <= a1o;
            a1o_syn <= a1o_r;
        end
    end

    always@(negedge clk_1 or negedge rst_n1)begin //注意这里用下降沿触发
        if(!rst_n1)
            a2i_2 <= 0;
        else
            a2i_2 <= a1o_syn;
    end

    assign a2o = a2i_2 & clk_1;

//下半部分时钟控制的逻辑   
    wire a3o, a4o;
    reg a3o_r, a3o_syn;
    assign a3o = select & !a2i_2;

    always@(posedge clk_2, negedge rst_n2)begin //打两拍同步
        if(!rst_n2)begin
            a3o_r <= 0;
            a3o_syn <= 0;
        end
        else begin
            a3o_r <= a3o;
            a3o_syn <= a3o_r;
        end
    end

    always@(negedge clk_2 or negedge rst_n2)begin //注意这里用下降沿触发
        if(!rst_n2)
            a4i_2 <= 0;
        else
            a4i_2 <= a3o_syn;
    end

    assign a4o = a4i_2 & clk_2;

//输出的与门逻辑
    assign clk_out = a2o | a4o;
endmodule

 

文中图3来源于《数字IC设计入门》 


http://www.kler.cn/a/137206.html

相关文章:

  • 在uniapp Vue3版本中如何解决webH5网页浏览器跨域的问题
  • 国家认可的人工智能从业人员证书如何报考?
  • fastdds:idl
  • 后端使用Spring Boot框架 + 前端VUE 实现滑动模块验证码
  • python如何获取excel单元格文字是否加粗
  • 机器学习中做时间序列模型考虑把时间作为特征分析
  • Idea2023 Springboot web项目正常启动,页面展示404解决办法
  • 论文《A recurrent latent variable model for sequential data》笔记:详解VRNN
  • 京东商品详情数据接口【京东API接口开发系列】,监控京东价格走势,接口代码示例,可高并发批量获取
  • 二百零四、Flume——登录监听窗口报错Ncat: bind to :::44444: Address already in use. QUITTING.
  • 005 OpenCV直方图
  • 【Spring】SpringBoot的扩展点之ApplicationContextInitializer
  • INFINI Labs 产品更新 | 发布 Easysearch Java 客户端,Console 支持 SQL 查询等功能
  • 基于java的学生考勤信息管理系统设计【附源码】
  • 面向未来的自动化:拥抱机器人即服务(RaaS)
  • Linux:动静态库
  • FlinkCDC数据实时同步Mysql到ES
  • MQTT.js
  • 鸿蒙:Harmony开发基础知识详解
  • 使用Grpc实现高性能PHP RPC服务
  • 智慧安防监控系统EasyCVR(v3.4)开放协议的介绍及使用
  • Qt专栏3—Qt项目创建Hello World
  • datafilecopy header validation failure for file +DATA/orcl/datafile/file1.ora
  • 电脑便签工具推荐哪个?电脑上好用的便签软件使用哪一款
  • 【监控系统】日志可视化监控体系ELK搭建
  • C#入门(7):接口详细介绍与代码演示