题解 | #多bit MUX同步器#

多bit MUX同步器

https://www.nowcoder.com/practice/30e355a04a454e16811112cb82af591e

思路

这个题我是看别人的题解。因为看题目我是一脸懵。根本不知道在干什么......

其实题目表达得不太清楚,题目是说,有两个时钟域clk_a和clk_b。现在来自clk_a的数据data_in让我们同步到clk_b的时钟域中去。题目还有一个条件没有说清楚,就是一个clk_b的时间是比clk_a长的,clk_b打一拍的时间够clk_a打两拍。

题目理解了,下面就是做题。这本质上就是一个跨时钟域处理的问题,跨时钟域处理涉及到亚稳态的问题。

什么是亚稳态呢?

举一个例子。在抛硬币的时候,硬币可以是正面也可以是反面,这是确定的。但是硬币在空中的过程,我们是不知道它是正面还是反面的。假设把触发器看做硬币,当信号到达触发器相当于抛硬币,在信号输出触发器相当于抛硬币的结果;如果在信号到达触发器时,时钟信号正好在改变,就会造成采样了多种输入信号,在一段时间内,输出信号也是不稳定的。这就是亚稳态。

如何解决亚稳态呢?在时钟域对输入信号进行多次采样。

代码

`timescale 1ns/1ns

module mux(
	input 				clk_a	, 
	input 				clk_b	,   
	input 				arstn	,
	input				brstn   ,
	input		[3:0]	data_in	,
	input               data_en ,

	output reg  [3:0] 	dataout
);
	
	reg [3:0]data_in_reg;
    reg data_en_reg;
    reg data_en_b0,data_en_b1;
    //对data_in和data_en打一拍
    always @(posedge clk_a or negedge arstn ) begin
        if (!arstn)begin
            data_in_reg<=0;
            data_en_reg<=0;
        end
        else begin
            data_in_reg<=data_in;
            data_en_reg<=data_en;
        end
    end
    //对data_en在clk_b下打两拍
    always @(posedge clk_b or negedge brstn ) begin
        if (!brstn)begin
            data_en_b0<=0;
            data_en_b1<=0;
        end
        else begin
            data_en_b0<=data_en_reg;
            data_en_b1<=data_en_b0;
        end
    end
    //待同步之后输出dataout
    always @(posedge clk_b or negedge brstn ) begin
        if (!arstn)dataout<=0;
        else begin
            if(data_en_b1)dataout<=data_in_reg;
        end
    end

endmodule

问题

有几个问题:

1.为什么data_in和data_en都要在clk_a下打一拍?

  • 为了避免毛刺。打一拍让data_in和data_en信号都稳定。

2.为什么要把data_en在clk_b下打两拍?

  • 刚刚提到过,跨时钟域容易出现亚稳态问题。为了避免它,就要尽量打多的拍。那为什么打两拍而不打一拍呢?原因是能多打拍就多打拍。为什么打两拍而不打三拍呢?因为题目说data_en能在clk_b下稳定3拍。之前data_en_reg消耗了半拍clk_b,所以后面只能打两拍了。两拍是上限了。

3.为什么下面这段代码就能实现data_en_reg打两拍?

    always @(posedge clk_b or negedge brstn ) begin
        if (!brstn)begin
            data_en_b0<=0;
            data_en_b1<=0;
        end
        else begin
            data_en_b0<=data_en_reg;
            data_en_b1<=data_en_b0;
        end
    end

注意,data_en_b0<=data_en_reg;和data_en_b1<=data_en_b0;都是非阻塞赋值。也就是执行data_en_b1<=data_en_b0时data_en_b1得到的其实是data_en_b0的旧值,这两条语句是同时发生的。所以这样写也能实现打两拍的功能。

全部评论

相关推荐

野猪不是猪🐗:这种直接口头上答应,骗面试,面完了直接拉黑,相当于给自己攒面经了(
点赞 评论 收藏
分享
浪子陪都:简历最优秀的地方放到了后面,国奖,校级奖学金这些是最亮眼的。说明你跟同级别的学生不一样。 建议台灯这个,PCB布局布线这个词汇不专业,业内是PCB Layout,第二,单片机的板子一般不用考虑SI,PI 都是低速信号,只要遵循3W原则就好了。 单片机的项目太low了,技能这块,你要看一下BOSS直聘的招聘要求,按照别人的要求写,一些关键词可以增加你简历被检索到的概率。 主修课程不用写,这个没有人去关注的。
点赞 评论 收藏
分享
评论
5
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务