异步复位,同步释放

Scroll Down

前言

在实际工程中,不同的模块可能时钟域不同,这种情况很常见。复位的基本目的是使器件进入到可以稳定工作的确定状态,工程实践中,确实见过由于未做异步复位的同步处理,而出现大概率系统死机现象。

同步复位与异步复位

同步复位

同步复位就是指复位信号只有在时钟上升沿到来时有效。

always @ (posedge clk_sys)
begin
    if (rst_n == 1'b0)
    begin
        dout <= #U_DLY 'b0;
    end
    else
    begin
        dout <= #U_DLY din;
    end
end

异步复位

在实际工程中常用的是异步复位,异步复位是指无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。

always @ (posedge clk_sys or negedge rst_n)
begin
    if (rst_n == 1'b0)
    begin
        dout <= #U_DLY 'b0;
    end
    else
    begin
        dout <= #U_DLY din;
    end
end

为什么要用异步复位

  • 由于系统触发器等器件都只预置异步复位端口,所以同步复位的电路实现比异步复位的电路实现要浪费更多电路资源。
  • 同步复位信号的有效时长必须大于时钟周期才能真正被系统识别并完成复位。同时还要考虑如:时钟偏移、组合逻辑路径延时、复位延时等因素。

异步复位带来的问题

  • 异步复位信号容易受到毛刺的影响。
  • 由于不同模块的时钟域可能不同,如果全局异步复位的释放时刻恰好在某个触发器的亚稳态窗口期间,违反了建立时间保持时间的时序要求,就会造成该触发器产生亚稳态。

同步释放

为了解决上述提出的问题,需要对异步复位信号采用同步释放的设计。由于复位信号是单bit信号,很容易想到可以用两级触发器对不同时钟域复位信号分别进行缓冲完成同步。

always @(posedge clk_A_i or negedge rst_n_i) 
begin
    if(rst_n_i == 1'b0)
        rst_A_r <= #U_DLY 2'b00;
    else
        rst_A_r <= #U_DLY {rst_A_r[0],1'b1};
end
assign rst_A_n_o = rst_A_r[1];

always @(posedge clk_B_i or negedge rst_n_i) 
begin
    if(rst_n_i == 1'b0)
        rst_B_r <= #U_DLY 2'b00;
    else
        rst_B_r <= #U_DLY {rst_B_r[0],1'b1};
end
assign rst_B_n_o = rst_B_r[1]

通过上述代码可以看到,异步复位信号仅在时钟上升沿来临时释放,这也就是所谓的同步释放。