一、同步复位
总结:同步复位是在时钟沿到到达时有效,这就意味着复位信号不会出现亚稳态,同时复位信号上的毛刺可以被滤除。且要复位成功需要保持超过一个时钟周期。
优点:
- 可防止亚稳态和毛刺。
- 可以使电路设计为同步电路,有利于时序分析。
仿真三种情况:(复位时间不足一个时钟周期、复位时间超过一个时钟周期、一个高频复位毛刺):
module rst_test(
input clk , //工作时钟
input rst_n , //复位,低电平有效
input in , //输入信号
output reg out //输出信号
);
//-----------输出模块-------------------------------
always@(posedge clk )begin
if(!rst_n)
out <= 1'b0; //复位将输出置零
else
out <= in; //其他时候将输入赋值给输出
end
endmodule
//------------------------------------------------
//--同步复位仿真
//------------------------------------------------
`timescale 1ns/1ns //时间单位/精度
//------------<模块及端口声明>----------------------------------------
module tb_rst_test();
reg clk ;
reg rst_n ;
reg in ;
wire out ;
//------------<例化被测试模块>----------------------------------------
rst_test rst_test_inst(
.clk (clk) ,
.rst_n (rst_n) ,
.in (in) ,
.out (out)
);
//------------<设置初始测试条件>----------------------------------------
initial begin
clk = 1'b0;
rst_n <= 1'b0;
in <= 1'b1;
#5
rst_n <= 1'b1;
#6
rst_n <= 1'b0;
#18
rst_n <= 1'b1;
#39
rst_n <= 1'b0;
#21
rst_n <= 1'b1;
#25
rst_n <= 1'b0;
#3
rst_n <= 1'b1;
end
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk; //系统时钟周期20ns
endmodule
结果:
- 第1个复位时间不足一个时钟周期,导致复位不成功
- 第2个复位时间超过一个时钟周期,复位成功
- 最后一个复位信号上的高频毛刺信号没有对系统造成误复位
- 输出信号在第一个时钟上升沿到来之前是未知状态
二、异步复位
异步复位:异步复位指的是无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。当时钟上升沿检测到复位信号,执行复位操作。
优点:大部分的器件库都有异步复位的端口,因此异步复位可以节省资源。
缺点:
- 复位信号容易受到毛刺的影响
- 因为是异步逻辑,无法避免存在亚稳态。
恢复时间:复位信号变为无效后到时钟沿来临之间的所要维持的最小的时间。类似建立时间。
解除时间:复位信号变为无效时,与上一个时钟沿的最小间隔。对应保持时间。
注意:复位信号一定要满足恢复和解除时间,否则无法确定时钟是否起作用,即判断不了时钟沿是复位了还是没复位。
1、不满足复位恢复时间或者撤离时间,可能会导致亚稳态问题。(注意是可能)因为如果输出本身就是复位后的值,即使当前时钟沿不能判断是否复位,输出也是复位值,这时候就不会产生亚稳态,因为已经是复位态了。
2、不满足复位恢复时间或者撤离时间可能会导致不同FF复位状态不一致的问题。复位信号和时钟信号一样,通过复位网络到达各个触发器。复位网络具有非常大的扇出和负载,到达不同的触发器存在不同的延时,不满足复位恢复或者解除时间的情况下,就有可能在不同的触发器的不同时钟周期内进行解复位。
三、异步复位同步释放
所谓异步复位同步释放,就是在rst_n信号为低时,立刻进行复位,即复位信号与时钟相互独立;而rst_n信号由低到高释放时,为了防止亚稳态的出现,将rst_n信号用DFF向后延一周期,外部复位信号不会在出现释放时与clk信号竞争,整个系统将与全局时钟clk信号同步
- 异步复位:当复位信号拉低时,直接进入复位状态。
- 同步释放:当复位信号释放时,加入两级同步缓存器,电路不会立即释放,而是同步到时钟有效时再进行释放。
module rst_crtl(
input clk,
input rst_n,
output reset
);
reg rst_n0,rst_n1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rst_n0 <= 0;
rst_n1 <= 0;
end
else
begin
rst_n0 <= rst_n;
rst_n1 <= rst_n0;
end
end
assign reset = rst_n1;