你的反压是怎么设计的?

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

FPGA的设计中,一个前级模块A向下游模块B发送数据,如下图所示,当下游模块B不能及时处理数据时,希望前级模块A停止发送数据,这个时候模块B会通过一个反压信号给到模块A,告诉模块A,不要再给我发数据了。这就是一种最常见,也是用得最普遍的一种发压场景。

那究竟要如何设计反压呢?看似简单,其实也不简单,处理不好的话对系统的稳定性和性能会带来一定的影响。本文介绍几种常见的反压方式,并给出他们的一些优缺点。

立即反压

所谓立即反压,就是指下游模块给出反压后,前级模块立即停止发包,如下图所示:

一共有7个数据,但是真正能被下游模块接收的数据只有6个,其中数据E在发送的时候因为ready无效,所以不能被接收。如果对axi_stream接口比较了解的话,可以看出,这就是axi_stream接口,只有在valid和ready同时有效的时候的数据才能被接收。

它的优点就是能立即反压,尤其是下游模块没有缓存的时候。另外就是这种接口是标准接口,和外部模块对接的时候不会有歧义。缺点就是因为需要立即反压,组合逻辑处理比较简单,如果用时序逻辑,控制起来不是很方便。

将满反压

如果下游接收模块有缓存,一般是fifo或者ram。当缓存快要满的时候,会给前级模块反压,这就是将满反压。如下图所示:

这种反压的特点就是下游模块给出反压信号后,前级模块还可以继续写入一些数据,一般不超过5拍。上图中,虽然afull = 1了,但是前级模块还会继续写入2个数据,数据F和数据G。同时下游模块也要控制好缓存的水限,在给出反压信号后还要预留一定的缓存空间,具体多少,需要和前级模块配合好,笔者的经验,一般预留8个以上。

如下图所示缓存的深度为128,当数据写满100以后给出反压,此时缓存还可以写入28个数据,该缓存的水限就为100。

这种将满反压的优点就是处理非常方便,只要下游模块不反压,就可以不停地写入数据,控制非常方便,另外下游模块缓存的深度和前级模块无关,一般用于项目内部模块之间。至于缺点,如果一定要找一个缺点,那就是下游模块必须有缓存,而立即反压可以不需要。

另外,对于缓存,到底是用ram还是用fifo,应该根据场景来确定,通常情况下用fifo可以满足大部分的应用场景。(FIFO和RAM,到底用哪个?

整包反压

上述将满反压,如果反压频繁的话,会给前级模块的处理带来一点点的复杂度,为了简化这种反压带来的影响,还有一种叫整包反压。和将满反压相比,就是下游模块给出反压信号后,前级模块会把当前的数据报文全部发送给下游模块,如下图所示:

当数据在传输的过程中,如果下游模块给出反压使得afull = 1,前级模块会继续发送报文,直到报文的eop为止。这种场景下,首先需要约定报文的最大长度,假定为MAX_LEN,那么对下游的缓存就会有要求,其容量至少为MAX_LEN,考虑到流水性能,其容量要为2*MAX_LEN,同时水限的设置要保证反压后的空间至少能存放一个报文。

这种方案的优点是控制简单,只要开始发送的时候不反压,就可以把当前的报文全部发送完。缺点就是当约定的MAX_LEN比较大时,需要较多的缓存开销。

小结

反压是FPGA设计中的一个最基本且重要的话题,在实际应用中,模块与模块之间的反压要做好“逐级反压”,当反压点与缓存较远的时候,尤其要考虑在途的数据(计算在途数据量),反压后的空间要能缓存住在途数据。除了上述的几种方案外,请求应答接口某种意义上也是一种反压的设计,只是性能较低罢了,一般不建议采用。

最新文章

最新文章