集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1492|回复: 3

Verilog基本电路设计之一: 单bit跨时钟域同步

[复制链接]
d643189658 发表于 2017-8-11 17:56:56 | 显示全部楼层 |阅读模式
Verilog基本电路设计之一: 单bit跨时钟域同步
首先介绍异步信号的跨时钟域同步问题。一般分为单bit的控制信号同步,以及多bit的数据信号同步。多bit的信号同步会使用异步FIFO完成,而单bit的信号同步,又是时钟无缝切换电路以及异步FIFO电路的设计基础,这里先介绍单bit信号同步处理。
clka域下的信号signal_a,向异步的clkb域传递时,会产生亚稳态问题。所有的亚稳态,归根结底就是setup/hold时间不满足导致。在同一个时钟域下的信号,综合以及布线工具可以在data路径或者clock路径上插入buffer使得每一个DFF的setup/hold时间都满足;但是当signal_a在clkb域下使用时,由于clka与clkb异步,它们的相位关系不确定,那么在clkb的时钟沿到来时,无法确定signal_a此时是否处于稳定无变化状态,也即setup/hold时间无法确定,从而产生亚稳态。这种异步信号在前后端流程里面是无法做时序分析的,也就是静态时序分析里常说的false_path。
消除亚稳态,就是采用多级DFF来采样来自另一个时钟域的信号,级数越多,同步过来的信号越稳定。对于频率很高的设计,建议至少用三级DFF,而两级DFF同步则是所有异步信号处理的最基本要求。
单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采到。电平信号的同步处理,一般用于知道确定的时钟频率大小关系或者极慢时钟下的信号向极快时钟域传递时使用,简单处理如下:

always @ (posedge clkb or negedge rst_n)begin
    if (!rst_n) begin
       levl_b_d1 <= #DLY 1'b0;
       levl_b_d2 <= #DLY 1'b0;
       levl_b_d3 <= #DLY 1'b0;
    end
    else begin
       levl_b_d1 <= #DLY levl_a_in;
       levl_b_d2 <= #DLY levl_b_d1;
       levl_b_d3 <= #DLY levl_b_d2;
    endend

assign puls_b_pos = levl_b_d2 & (~levl_b_d3);
assign puls_b_neg = levl_b_d3 & (~levl_b_d2);
assign levl_b_out  = levl_b_d2;

上面三个输出分别是经过同步之后,clkb下可以使用的0变1脉冲信号,1变0脉冲信号以及电平信号。再次强调:levl_a_in必须是clka的DFF信号!下面是更常见的,clka下的脉冲信号,同步到clkb时钟域下,它对于clka与clkb的时钟频率关系没有任何限制,快到慢,慢到快都没问题。其主要原理就是先把脉冲信号在clka下展宽,变成电平信号,再向clkb传递,当确认clkb已经“看见”信号同步过去之后,再清掉clka下的电平信号。脉冲信号同步处理电路,有两个地方使用了上面的电平信号同步处理原则,请仔细揣摩原因。详细见下面的RTL,其中省略了信号定义声明:

module sync_pulse (
    // input
        rst_n,        // system reset
      clka,         // clockA
      clkb,         // clockB
      puls_a_in,    // pulse input from clka
    // output
      puls_b_out,  // pulse output in clkb
     levl_b_out    // level output in clkb
     );

parameter DLY =  1;  //

always @ (posedge clka or negedge rst_n)
begin
    if (rst_n == 1'b0)
        signal_a <= # DLY 1'b0 ;
    else if (puls_a_in)
        signal_a <= # DLY 1'b1 ;
    else if (signal_b1_a2)
        signal_a <= # DLY 1'b0 ;
    else ;
end

always @ (posedge clkb or negedge rst_n)
begin
    if (rst_n == 1'b0)
        signal_b <= # DLY 1'b0 ;
    else
        signal_b <= # DLY signal_a ;
end

always @ (posedge clkb or negedge rst_n)
begin
    if (rst_n == 1'b0) begin
        signal_b_b1 <= # DLY 1'b0 ;
        signal_b_b2 <= # DLY 1'b0 ;
    end
    else begin
        signal_b_b1 <= # DLY signal_b ;
        signal_b_b2 <= # DLY signal_b_b1 ;
    end
end

always @ (posedge clka or negedge rst_n)
begin
    if (rst_n == 1'b0) begin
        signal_b1_a1 <= # DLY 1'b0 ;
        signal_b1_a2 <= # DLY 1'b0 ;
    end
    else begin
        signal_b1_a1 <= # DLY signal_b_b1 ;
        signal_b1_a2 <= # DLY signal_b1_a1 ;
    end
end

assign puls_b_out = signal_b_b1 & (~signal_b_b2) ;
assign levl_b_out = signal_b_b1 ;

endmodule
zxopenljx 发表于 2021-1-8 20:30:19 | 显示全部楼层
Verilog基本电路设计之一: 单bit跨时钟域同步
zxopenluyutong 发表于 2021-1-8 23:04:44 | 显示全部楼层
Verilog基本电路设计之一: 单bit跨时钟域同步
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-4-20 03:27 , Processed in 0.059701 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表