单bit电平信号以及脉冲信号的跨时钟域处理


前言

单bit信号的跨时钟域处理,可以分为电平信号的跨时钟域处理和脉冲信号的跨时钟域处理。

一、电平信号的跨时钟域处理

电平信号,就是说clka下的信号signal_a在clkb看来,是一个很宽的信号,会保持多个clkb的时钟周期,一定能被clkb采到。这种情况,只需要在clkb时钟域下用至少两级DFF将signal_a打两拍即可。

特别需要强调的是,此时signal_a必须是clka下的寄存器信号。如果signal_a是clka下的组合逻辑信号,一定要先在clka下用DFF打一拍,再使用两级DFF向clkb传递。这是因为clka下的组合逻辑信号会有毛刺,在clka下使用时会由setup/hold时间保证毛刺不会被clka采到,但由于异步相位不确定,组合逻辑的毛刺却极有可能被clkb采到。

具体代码如下:

module level_signal_sync(
        input    wire   clk_b,
        input    wire   rst_n,
        input    wire   levl_a,
        output   wire   levl_b,
        output   wire   levl_b_pos,
        output   wire   levl_b_neg              
                        );
reg   levl_b_syn1, levl_b_syn2, levl_b_syn3;

always @(posedge clk_b, negedge rst_n) begin
    if(rst_n == 1'b0) begin
        levl_b_syn1 <= #1 1'b0;
        levl_b_syn2 <= #1 1'b0;
        levl_b_syn3 <= #1 1'b0;
    end
    else begin
        levl_b_syn1 <= #1 levl_a;
        levl_b_syn2 <= #1 levl_b_syn1;
        levl_b_syn3 <= #1 levl_b_syn2;
    end
end
assign levl_b = levl_b_syn2;
assign levl_b_pos = levl_b_syn2 && (~levl_b_syn3);
assign levl_b_neg = (~levl_b_syn2) && levl_b_syn3;
endmodule

上面三个输出分别是经过同步之后,clkb下可以使用的电平信号、0变1脉冲信号以及1变0脉冲信号。再次强调:levl_a必须是clka的DFF信号!

二、脉冲信号的跨时钟域处理

下面是更常见的,clka下的脉冲信号,同步到clkb时钟域下,它对于clka与clkb的时钟频率关系没有任何限制,快到慢,慢到快都可以。其主要原理就是先把脉冲信号在clka下展宽,变成电平信号,再向clkb传递,当确认clkb已经“看见”信号同步过去之后,再清掉clka下的电平信号。
具体代码如下:

module pulse_signal_sync(
       input   wire   clk_a,
       input   wire   clk_b,
       input   wire   rst_n,
       input   wire   puls_a,
       output  wire   puls_b,
       output  wire   levl_b
                        );
reg   levl_a;
reg   levl_b_syn1, levl_b_syn2, levl_b_syn3;
reg   levl_b2a_syn1, levl_b2a_syn2;

//生成clka时钟域的脉冲展宽信号
always @(posedge clk_a, negedge rst_n) begin
    if(rst_n == 1'b0) begin
        levl_a <= #1 1'b0;
    end
    else if(puls_a) begin
        levl_a <= #1 1'b1;
    end
    else if(levl_b2a_syn2) begin
        levl_a <= #1 1'b0;
    end
    else begin
        levl_a <= #1 levl_a;
    end
end

//在clkb时钟域采样展宽后的信号
always @(posedge clk_b, negedge rst_n) begin
    if(rst_n == 1'b0) begin
        levl_b_syn1 <= #1 1'b0;
        levl_b_syn2 <= #1 1'b0;
        levl_b_syn3 <= #1 1'b0;
    end
    else begin
        levl_b_syn1 <= #1 levl_a;
        levl_b_syn2 <= #1 levl_b_syn1;
        levl_b_syn3 <= #1 levl_b_syn2;
    end
end

//在clka时钟域内同步clkb时钟域内的展宽信号,以生成反馈信号
always @(posedge clk_a, negedge rst_n) begin
    if(rst_n == 1'b0) begin
        levl_b2a_syn1 <= #1 1'b0;
        levl_b2a_syn2 <= #1 1'b0;
    end
    else begin
        levl_b2a_syn1 <= #1 levl_b_syn2;
        levl_b2a_syn2 <= #1 levl_b2a_syn1;
    end
end

assign puls_b = levl_b_syn2 && (~levl_b_syn3);
assign levl_b = levl_b_syn2;
endmodule

总结:
1、慢时钟域到快时钟域的单bit信号,一般可以直接通过打两拍的方式来处理。
2、快时钟域到慢时钟域的脉冲信号,由于脉冲宽度较窄,采用打两拍的方式在慢时钟域内有可能采样不到,因此需要采用握手的方式处理。

3、首先是在快时钟域下将脉冲展宽(快时钟域下脉冲信号到来时将电平信号拉高,慢时钟域下的反馈信号到来后将电平信号拉低)。
4、展宽后的电平信号在慢时钟域下打两拍,结果作为电平输出信号。
5、慢时钟域下的电平输出信号在快时钟域下打两拍,结果作为反馈信号。
6、在慢时钟域下采用边沿检测的方式,可以生成脉冲输出信号。

  • 7
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值