1、复位的重要性
数字电路中寄存器和 RAM 在上电之后默认的状态和数据是不确定的,如果有复位,我们可以把寄存器 复位到初始状态 0,RAM 的数据可以通过复位来触发 RAM 初始化到全 0。那可能很多人会问为什么是全 0呢?其实一般逻辑起始都是从 0 开始变化的,这个是根据设计的需要设定的一个值,如果设计需要寄存器 上电复位为 1,也是可以的。还有一种情况是逻辑进入了错误的状态,通过复位可以把所有的逻辑状态恢复 到初始值,如果没有复位,那么逻辑可能永远运行在错误的状态。
因此复位功能是很重要的一个功能。数字电路的复位通常可分为:同步复位与异步复位。
2、同步复位
同步复位:同步复位指的是当时钟上升沿检测(有效沿)到复位信号,执行复位操作,有效的时钟沿是前提。
Verilog代码:
//*******************同步复位模块**************************
//-----------端口定义-------------------------------
modulerst_test(
inputclk,//工作时钟
inputrst_n,//复位,低电平有效
inputin,//输入信号
outputregout//输出信号
);
//-----------输出模块-------------------------------
always@(posedge clk )begin
if(!rst_n)
out <= 1'b0;//复位将输出置零
else
out <= in;//其他时候将输入赋值给输出
end
endmodule
使用Quartus II综合出的RTL如下:
可以看到,生成的触发器并没有复位置位端,而是生成了一个选择器,同步复位信号rst_n用作了选择器的使能,从而实现复位清零的作用。
用如下Testbench进行仿真(复位时间不足一个时钟周期、复位时间超过一个时钟周期、一个高频复位毛刺):
//------------------------------------------------
//--同步复位仿真
//------------------------------------------------
`timescale 1ns/1ns//时间单位/精度
//------------<模块及端口声明>----------------------------------------
module tb_rst_test();
reg clk;
reg rst_n;
regin;
wireout;
//------------<例化被测试模块>----------------------------------------
rst_testrst_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个复位时间超过一个时钟周期,复位成功
最后一个复位信号上的高频毛刺信号没有对系统造成误复位
输出信号在第一个时钟上升沿到来之前是未知状态
同步复位电路的优点:
有利于仿真器的仿真
基本上没有亚稳态问题
可以使所设计的系统成为 100%的同步时序电路,有利于时序分析
由于只在时钟有效电平到来时才有效,所以可以滤除高于时钟频率的复位毛刺
同步复位电路的缺点:
复位信号的有效时长必须大于时钟周期,才能真正被系统识别并完成复位任务。同时还要考虑延时因素
大多数的FPGA的DFF都只有异步复位端口,采用同步复位的话,综合器就会在寄存器的数据输入端口插入组合逻辑,这样会耗费逻辑资源
3、异步复位
异步复位:异步复位指的是无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。当时钟上升沿检测到复位信号,执行复位操作。
Verilog代码:
//*******************同步复位模块**************************
//-----------端口定义-------------------------------
modulerst_test(
inputclk,//工作时钟
inputrst_n,//复位,低电平有效
inputin,//输入信号
outputregout//输出信号
);
//-----------输出模块-------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
out <= 1'b0;//复位将输出置零
else
out <= in;//其他时候将输入赋值给输出
end
endmodule
使用Quartus II综合出的RTL如下:
可以看到,异步复位信号rst_n直接接入了触发器的异步复位端,从而实现复位清零的作用。
依然使用之前用的Testbench进行仿真,结果如下:
从仿真结果可以看到:
只要复位信号被置为低电平,就执行复位操作,与时钟无关
高频毛刺信号会对系统造成误复位
在不考虑亚稳态的前提下,复位时间没有要求
a、在复位信号释放(release)的时候容易出现问题。具体就是说:倘若复位释放时恰恰在时钟有效沿附近,就很容易使寄存器输出出现亚稳态,从而导致亚稳态。
b、复位信号容易受到毛刺的影响
异步复位电路的优点:
大多数目标器件库的dff都有异步复位端口,因此采用异步复位可以节省资源
设计相对简单,异步复位信号识别方便,而且可以很方便的使用FPGA的全局复位端口GSR
异步复位电路的缺点:
复位信号容易受到毛刺的影响
因为是异步逻辑,无法避免地存在亚稳态问题
关于异步复位还需要考虑:
恢复时间(Recovery Time)是指异步控制信号(如寄存器的异步清除和置位控制信号)在“下个时钟沿”来临之前变无效的最小时间长度。这个时间的意义是,如果保证不了这个最小恢复时间,也就是说这个异步控制信号的解除与“下个时钟沿”离得太近(但在这个时钟沿之前),没有给寄存器留有足够时间来恢复至正常状态,那么就不能保证“下个时钟沿”能正常作用,也就是说这个“时钟沿”可能会失效。
去除时间(Removal)是指异步控制信号(如寄存器的异步清除和置位控制信号)在“有效时钟沿”之后变无效的最小时间长度。这个时间的意义是,如果保证不了这个去除时间,也就是说这个异步控制信号的解除与“有效时钟沿”离得太近(但在这个时钟沿之后),那么就不能保证有效地屏蔽这个“时钟沿”,也就是说这个“时钟沿”可能会起作用。
换句话来说,如果你想让某个时钟沿起作用,那么你就应该在“恢复时间”之前是异步控制信号变无效,如果你想让某个时钟沿不起作用,那么你就应该在“去除时间”过后使控制信号变无效。如果你的控制信号在这两种情况之间,那么就没法确定时钟沿是否起作用或不起作用了,也就是说可能会造成寄存器处于不确定的状态。而这些情况是应该避免的。所以恢复时间和去除时间是应该遵守的。
4、异步复位、同步释放
结合两种复位的优点,可以使用异步复位、同步释放设计,Verilog代码如下:
//*******************同步复位模块**************************
//-----------端口定义-------------------------------
modulerst_test(
inputclk,//工作时钟
inputrst_n,//复位,低电平有效
inputin,//输入信号
outputregout//输出信号
);
//-----------reg定义-------------------------------
reg arst_n_r;
reg arst_n;
//-----------复位信号同步模块-------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
arst_n_r <= 1'b0;//复位将输出置零
arst_n <= 1'b0;//复位将输出置零
end
else begin
arst_n_r <= 1'b1;//跟接rst_n是一样的,都是逻辑1
arst_n <= arst_n_r;
end
end
//-----------输出模块-------------------------------
always@(posedge clk or negedge arst_n)begin
if(!arst_n)
out <= 1'b0; //复位将输出置零
else
out <= in; //其他时候将输入赋值给输出
end
endmodule
综合出来的RTL视图:
实际的电路图如下:
复位信号 rst_sync_n 由高拉低时实现 y 寄存器的异步复位。同步释放,这个是关键,即当复位信号 rst_async_n 撤除时(由低拉高),由于双缓冲电路(双触发器)的作用,rst_sync_n 不会随着rst_async_n 的 撤除而撤除。假设 rst_async_n 撤除时发生在 clk 上升沿,如果不加此电路则可能发生亚稳态事件,但是加上此电路以后,假设第一级 D 触发器 clk 上升沿时 rst_async_n 正好撤除,(第一个 DFF 此时是处于亚稳态 的;假设此时识别到高电平;若是识别到低电平,则增加一个 Delay)则 DFF1 输出高电平,此时第二级触发器也会更新输出,但是输出值为前一级触发器 clk 来之前时的 Q1 输出状态,显然 Q1 之前为低电平,所以第二级触发器输出保持复位低电平,直到下一个 clk 来之后,才随着变为高电平,即同步释放。
使用如下Testbench进行仿真:
//------------------------------------------------
//--同步复位仿真
//------------------------------------------------
`timescale 1ns/1ns//时间单位/精度
//------------<模块及端口声明>----------------------------------------
module tb_rst_test();
reg clk;
reg rst_n;
regin;
wireout;
//------------<例化被测试模块>----------------------------------------
rst_testrst_test_inst(
.clk(clk),
.rst_n(rst_n),
.in(in),
.out (out)
);
//------------<设置初始测试条件>----------------------------------------
initial begin
clk = 1'b0;
rst_n <= 1'b0;
in <= 1'b1;
#25
rst_n <= 1'b1;
#6
rst_n <= 1'b1;
#18
rst_n <= 1'b1;
#39
rst_n <= 1'b0;
#21
rst_n <= 1'b1;
end
//------------<设置时钟>----------------------------------------------
always #10 clk = ~clk;//系统时钟周期20ns
endmodule
仿真结果如下:
可以看到:复位是异步进行的,一旦复位信号为低电平,则输出复位,而复位的撤除则被同步到了时钟域下。如此一来,既解决了同步复位的资源消耗问题,也解决了异步复位的亚稳态问题。其根本思想,也是将异步信号同步化。
声明: 本文转载自csdn:孤独的单刀,如涉及作品内容、版权和其它问题,请于联系工作人员微(in0723mango),我们将在第一时间和您对接删除处理! 投稿/招聘/广告/课程合作/资源置换 请加微信:13237418207
Xilinx FPGA的约束设计和时序分析总结
全部0条评论
快来发表一下你的评论吧 !