题解 | #时钟切换#

时钟切换

http://www.nowcoder.com/practice/1de5e9bf749244cb8e5908626cc36d36

解题思路

题目中说了是两个同步的倍频时钟clk0 clk1,已知clk0是clk1的二倍频,属于相关时钟,避免切换时毛刺出现,只需要在组合逻辑的基础上添加下降沿触发的DFF。原理图如下:

alt

那么为什么要使用下降沿触发的DFF呢?

原因是这样,所谓去除毛刺,就是要避免毛刺的产生,那么得先明白毛刺是如何产生的,其实只要两个时钟相反时切换都换产生毛刺,如果没有DFF,比如,在clk1为低电平时,sel马上切换到clk0,恰巧clk0为高电平,但高电平只剩一点了,所以便产生了一个高电平毛刺,当然同理也有低电平毛刺。

但在此时钟切换电路中,sel信号的传输存在着DFF的延迟,也就是说在时钟切换时,两个DFF的输出存在都是0的情况,此时clk_out输出为低电平,这段时间可能很短,如果在两个时钟都是高电平的时候切换,可能会产生低电平毛刺,所以考虑要在两个都为低电平的时候切换最为稳妥。

那么使用下降沿触发的DFF,尽管sel已经有切换指令了,但需要等到下降沿后才通过DFF传到后面,因为是下降沿,所以高电平已经结束了,切换过去可确保无毛刺。

代码实现

`timescale 1ns/1ns

module huawei6(
	input    wire    clk0    ,
	input    wire    clk1    ,
	input    wire    rst     ,
	input    wire    sel     ,
	output   wire    clk_out
);
    reg q0, q1;
    
    always@(negedge clk0 or negedge rst)
        if(!rst)
            q0 <= 0;
        else 
            q0 <= ~sel & ~q1;
    
    always@(negedge clk1 or negedge rst)
        if(!rst) 
            q1 <= 0;
         else 
            q1 <= sel & ~q0;

    assign clk_out = (q0 & clk0) | (q1 & clk1);
    
endmodule

截止目前2022年4月10日,此题目正确答案未能用过牛客网的测试示例,因为牛客网标准答案中2个DFF的驱动时钟搞反了。

全部评论
`timescale 1ns/1ns module huawei6( input wire clk0 , input wire clk1 , input wire rst , input wire sel , output reg clk_out ); reg q0, q1; always@(negedge clk1 or negedge rst) if(!rst) q0 <= 0; else q0 <= ~sel & ~q1; always@(negedge clk0 or negedge rst) if(!rst) q1 <= 0; else q1 <= sel & ~q0; always@(*)begin clk_out <= (q0 & clk0) | (q1 & clk1); end endmodule 这样就可以了 感谢楼主的答案
1 回复 分享
发布于 2022-04-11 15:51
请问这个原理图是怎么得出的?
3 回复 分享
发布于 2023-09-18 17:15 北京
2025-5-15,编译通过
点赞 回复 分享
发布于 2025-05-15 10:33 陕西
截止目前2024年10月4日,此题目正确答案仍然未能通过牛客网的测试实例,感谢前人经验的一天!!!
点赞 回复 分享
发布于 2024-10-04 16:28 陕西

相关推荐

2025-12-27 22:29
门头沟学院 Java
点赞 评论 收藏
分享
淬月星辉:专利是什么?至少描述一下吧,然后把什么计算机二级、普通话这种拉低格调的证书删掉,不然hr以为你没东西写
点赞 评论 收藏
分享
评论
67
6
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务