同步、异步复位、异步复位同步释放
1、同步复位
同步复位,顾名思义是复位信号和时钟同步,当时钟上升沿检测到复位信号,执行复位操作。同步复位没有用到寄存器的异步复位CLR端口,综合出来的实际电路只是把复位信号rst_n作为逻辑输入的使能信号。
同步复位代码:
//同步复位
module top
(
input clk,
input rst_n,
input a,
output reg b
);
always@(posedge clk)
begin
if(!rst_n)
b <= 1'b0;
else
b <= a;
end
endmodule
同步复位RTL视图:
同步复位增加了FPGA内部的资源消耗,同步复位在时钟信号clk的上升沿触发时进行系统是否复位判断,这降低了亚稳态出现概率(只是降低,不可能完全避免),它的缺点在于需要消耗更多的器件资源,无法充分利用专用的复位端口CLR。
2、异步复位
异步复位,无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。
异步复位代码:
//异步复位
module top
(
input clk,
input rst_n,
input a,
output reg b
);
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
b <= 1'b0;
else
b <= a;
end
endmodule
异步复位RTL视图:
FPGA的寄存器都有一个异步清零端(CLR),在这个端口一般接低电平有效的复位信号rst_n,即使设计中是高电平复位,实际综合后也会把异步复位信号反向后接到CLR端。
异步复位无需增加器件的额外资源,但是存在隐患,异步时钟域的亚稳态问题同样存在于异步复位信号和系统时钟 信号之间。
2.1、异步复位的隐患
通过一下实例分析异步复位存在的隐患:
//异步复位存在的隐患实例
module top
(
input clk,
input rst_n,
input a,
output reg b,
output reg c
);
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
b <= 1'b0;
else
b <= a;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
c <= 1'b0;
else
c <= b;
end
endmodule
正常情况下,在clk 的上升沿将c的值更新为b,b的值更新为a。一但进入复位,b,c都清零,但是并不能确定复位信号rst_n会在什么时候结束。
涉及到 建立时间和保持时间 参考博客:建立时间和保持时间
如果结束于b_reg和c_reg的{latch edge-setup,latch edge+hold time}时间之外,那么一切都会正常。如果出现在之内,复位信号的撤销(由低变高)出现在clk锁存数据的建立时间或者保持时间之内,此时clk检测到rst_n的状态就会是一个亚稳态(不确定是0还是1),就会导致输出数据的错误。
也有可能一个reg处于复位,另一个reg跳出了复位,均会影响系统的正常工作,如果更大的项目隐患就更大了。
3、异步复位、同步释放
为了消除亚稳态的产生,利用两个同一时钟沿触发的层叠寄存器,将异步信号同步化:
//异步复位、同步释放
module top
(
input clk,
input rst_n,
input a,
output reg b
);
reg rst_n_r;
reg rst_n_rr;
always@(posedge clk)
begin
{rst_n_rr,rst_n_r} <= {rst_n_r,rst_n};
end
always@(posedge clk or negedge rst_n_rr)
begin
if(!rst_n_rr)
b <= 1'b0;
else
b <= a;
end
endmodule
★★★如有错误,欢迎指导!!!