软复位的设计思路

本文转载自: FPGA的现今未微信公众号

在前面的文章中介绍过复位设计,本文说下软复位设计的一些事情。那何为软复位?一般指通过写寄存器的方式来实现的复位叫做软复位。和软复位相对的是硬复位,一般指通过外部pin脚或者其他逻辑提供的复位。

pin脚复位

先看一个最简单的复位,即由外部pin脚引入的硬复位,如下图所示,这种复位逻辑简单、直观。对于可以直接操作单板的项目来说,是非常方便友好的。

这种方案有个缺点,很多时候,我们是不方便直接接触单板,或者说从业务层面,需要通过软件或者上位机来复位单板,这就需要有不同场景下的软复位操作。

手动复位、手动解复位

我们要通过软件或者上位机来复位逻辑,这个时候就需要一个软硬件的交互通道(接口)来下发复位的指令,也就是软复位的操作。逻辑结构如下图所示:

具体操作一般就2个步骤:
(1)软件写软复位寄存器,使能软复位;
(2)软件写软复位寄存器,解软复位。
这种方案也非常的简单,直接写寄存器即可复位相关逻辑,但是有一个注意点:软复位不能复位配置通道逻辑,因为这个通道复位后,就无法实现解复位了。另外也有一个不方便的地方,就是必须手动解复位,更加“偷懒”的方法就是自动解复位。

手动复位、自动解复位

顾名思义,这种方案就是写软复位寄存器以后,逻辑会自动解复位。一种通用的结构如下图所示:

整个复位解复位的过程分成如下几个步骤:
1、通过配置通道写软复位寄存器;
2、软复位信号送到复位逻辑形成新的全局复位信号,图中红色箭头,用来复位整个逻辑;
3、软复位寄存器被复位后,软复位信号恢复成初始状态,即解除软复位;
4、解除软复位后,复位逻辑解除全局复位。

这个方案也有一个问题,就是写软复位寄存器后,整个逻辑会马上复位,2-3个cycle后会解复位。对于有的逻辑或者场景,有复位时间要求,这种情况怎么办?

手动复位、延时自动解复位

相比上述方案,延时自动解复位,即对软复位保持的时间有要求,比如要求软复位信号要保持32个cycle。这里需要引入一个软复位计时计数器。该寄存器有2个特点,第一个就是不能复位;第二个就是通过写软复位寄存器来启动计数,如下所示。

always@(posedge clk_sys)
begin
if((wen == 1'b1) && (waddr == SOFT_REG_ADDR)) begin
soft_rst_cnt <= 8'd1;
end
else if(soft_rst_cnt != 0) begin
soft_rst_cnt <= soft_rst_cnt + 8'd1;
end
else;
end

always(posedge clk_sys)
begin
soft_reset <= (soft_rst_cnt != 0)? 1'b1: 1'b0;
end

在这种方案里需要注意的就是软复位寄存器的逻辑不能被复位掉,否则就达不到对复位时间的要求。

延时复位、延时自动解复位

最后还有一种场景,就配置软复位寄存器以后,不能马上复位,要等到一定的时间后才能复位。如下图所示,在t1时刻配置软复位后不能马上复位逻辑,必须等到t2时刻才能真正开始复位,在t3时刻结束复位。为什么会有这样的要求?主要是在一些数据中心的方案场景下,有些逻辑如果在t1时刻正常传输数据,突然复位引起中断后,会造成挂死。那如何延迟呢?有2种场景。

第一种场景就是t1到t2这个时间段是已知的,比如最多128个cycle。这个实现比较简单,将上述代码做一个简单的修改即可。

always(posedge clk_sys)
begin
soft_reset <= (soft_rst_cnt[7] != 0)? 1'b1: 1'b0;
end

第二种场景就是t1到t2这个时间段是未知的,这个时候我们必须用一个状态信号来表示t1到t2这个时间。用这个状态信号的下降沿来触发t2时候的复位。也只需要将上面的代码做一个小小的修改。

always@(posedge clk_sys)
begin
if((state == 1‘b0) && (state_1dly == 1'b1)) begin
soft_rst_cnt <= 8'd1;
end
else if(soft_rst_cnt != 0) begin
soft_rst_cnt <= soft_rst_cnt + 8'd1;
end
else;
end

总之,在具体应用中,软复位的场景相对来说是要复杂一点点,配合复位同步化处理一起构成了整个系统的复位。