复位是我们经常用到的,不知道有多少人和我一样,没有注意过他的正式的用法,以及其中的奥妙.首先提出一个问题,在FPGA中为什么要有复位?在FPGA上电时我们的FPGA到底处于一个什么样的状态呢?在FPGA芯片中,其触发器、BLOCK RAM等记忆芯片默认,上电时为0(一些厂商)。也有场商的芯片默认为1,还有一些厂商上电时的逻辑状态根本不统一。因此FPGA中的复位第一为了保证芯片从一个确定的状态开始工作,FPGA中必须要有一个复位信号;第二确保系统经历了一次问题后,FPGA的行为能够恢复正确。
一、复位的方式以及优缺点
同步复位:指的是复位信号在时钟有效边沿到来时刻为有效,就只想一次复位。
优点 |
缺点 |
(1)由于同步复位是离散的,因此其非常有利于仿真器的仿真 (2)由于同步复位只有在时钟有效边沿到来时才生效,因此可以滤除高于时钟频率的毛刺,提高复位操作的可靠性; (3)使用同步复位的系统可以被设计成为纯粹的同步时序电路,这样会大大有利于FPGA项目开发流程中的时序约束与时序分析环节的工作,而且综合出来的FPGA设计的性能一般也会较高。 |
(1),必须保证复位信号的有效持续时间长度大于一个时钟周期,否则该复位信号很可能被当做毛刺滤除掉,从而系统将漏掉一次应有的复位动作 (2),由于同步复位信号与时钟的相关性很大,因此设计和实现时必须要考虑到各种延迟和时间参数,确保其能够被FPGA设计正确接收并做出相应动作 (3),由于大多数的寄存器都只有异步复位端口,因此,如果采用同步复位,那么编译器势会添加额外的细合逻辑,这样就会消耗较多的逻辑资源。 |
异步复位:无论时钟信号的有效边沿是否到来,只要复位信号有效,就执行复位操作,直到复位信号变为无效才停止复位,异步复位是持续的连续的。
优点 | 缺点 |
(1),由于大多数的寄存器都具有异步复位端口,因此采用异步复位可以节省资源。 |
(1),在异步复位信号释放的时候非常容易出现问题。原因有两点:第一,当异步复位信号释放的时刻和时钟有效边沿比较接近时,就很容易导致寄存器的输出出现亚稳态,而亚稳态就是电平信号的电压较病的状态,容易导致逻辑误判:第二,由于复位信号所管辖的寄存器非常之多,而这些寄存器又位于FPGA芯片牧布同地,,因此复位信号到达各个寄存器的路径延迟肯定是参差不齐的1所以,如果异步复位信号释改的时刻和时钟信号有效沿比较接近时,很可能导致一部分寄存器在该时钟有效治在前完成复位,而另一部分寄存器在该时钟有效沿之后才完成复位,那么由于这一时钟周期的 偏差,就很可能会导致后续的逻辑功能出现全面地混乱。 (2),异步复位宿母非常容易受到毛刺等干扰的影响。 |
二、语法以及寄存器比较
异步:Verilog 语法描述 always @(posedge clk or negedge rst_n ),在低电平有效时生成的寄存器。需要的资源如下图所示:
同步:Verilog描述 always @(posege clk) if(!s_rst_n)。需要的资源如下图所示:
三、最佳解决办法---异步复位同步释放
原理:
所谓异步复位和同步释放,是指复位信号是异步有效的,即复位的发生与clk无关。后半句“同步释放”是指复位信号的撤除(释放)则与clk相关,即同步的。下面说明一下如何实现异步复位和同步释放的。
RTL 视图:
异步复位:显而易见,rst_async_n异步复位后,rst_sync_n将拉低,即实现异步复位。
同步释放:这个是关键,看如何实现同步释放,即当复位信号rst_async_n撤除时,由于双缓冲电路的作用,rst_sync_n复位信号不会随着rst_async_n的撤除而撤除。
分析:假设rst_async_n撤除时发生在clk上升沿,如果不加此电路则可能发生亚稳态事件(在始终上升沿附近rst置1,这时候建立时间还不够长,数据可能还未打入寄存器,导致输出不确定)。但是加上此电路以后,假设第一级D触发器clk上升沿时rst_async_n正好撤除,则D触发器1输出高电平“1”,此时第二级触发器也会更新输出,但是输出值为前一级触发器次clk来之前时的Q1输出状态。显然Q1之前为低电平,顾第二级触发器输出保持复位低电平,直到下一个clk来之后,才随着变为高电平。即同步释放。
1 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 // Project Name : 3 // Website : https://home.cnblogs.com/lgy-gdeu/ 4 // Author : LGY GUET Uiversity 5 // Weixin : li15226499835 6 // Email : 15277385992@163.com 7 // File : 8 // Create : 2020 9 // Revise : 10 // Editor : sublime text{SUBLIME_VERSION}, tab size ({TABS}) 11 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 // Modification History: 13 // Date By Version Change Description 14 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 // {DATE} {TIME} LGY 1.0 ++++++++++++++++ 16 // ********************************************************************************* 17 `timescale 1ns/1ns 18 19 module ays_rst_sys_free( 20 21 input wire sclk , 22 input wire s_rst , 23 output wire sys_rst 24 ); 25 26 //============================================================================= 27 //+++++++++++++++++++++++++ Main Code +++++++++++++++++++++++++++++++ 28 //============================================================================= 29 30 reg rst_r0 ; 31 reg rst_r1 ; 32 33 always @(posedge sclk or posedge s_rst ) begin 34 if(s_rst) begin 35 rst_r0 <= 1'b1 ; 36 rst_r1 <= 1'b1 ; 37 end 38 39 else begin 40 rst_r0 <= 1'b0 ; 41 rst_r1 <= rst_r0 ; 42 end 43 end 44 45 46 assign sys_rst = rst_r1 ; 47 48 49 50 endmodule