问题提出:ready时序如何优化?
在valid/ready 握手协议中,valid 与 data的时序优化比较容易理解。
但是有时候,关键路径是在ready信号上,如何对ready信号打拍呢?
首先将把目标设计想象成一个黑盒子,如图1所示,我们的目标是将READY_DOWN通过打拍的方法获得时序优化。
(图1)
尝试直接对ready打一拍
(仅示例,非verilog代码。下同)
这样是行不通的。
一个简单的例子(case 1)就是你让READY_DOWN像一个时钟一个,间隔一个cycle起来一次,那么VALID_UP && READY_UP 与 VALID_DOWN && READY_DOWN无法同步,数据无法传输下去。
思路:将其分解成两个interfaces
将ready打拍的逻辑想象成一个黑盒子,去分析这个黑盒子的设计,分为up interface 和down interface将问题细化:
-
up interface 有VALID_UP, DATA_UP, READY_UP
-
down interface 有VALID_DOWN, DATA_DOWN, READY_DOWN
可以总结成下面的样子:
如果去解决刚才例子(case 1),那么这个黑盒子:
当READY_UP为高的时候,可以接受数据;
当READY_DOWN为高的时候, 如果我们有数据可发的话 ,我们可以向downstream发送数据;
是不是很像一个FIFO?
用FIFO去解决
将一个FIFO插在黑盒子这里,那么就会变成这样子:
(图2)
VALID_UP/READ_YUP ==> FIFO ==> VALID_DOWN/READY_DOWN
也就是:
现在问题变成了:如何设计这个FIFO呢?
- 这个FIFO深度多少?
- 怎么设计,能够保证READY_UP是READY_DOWN打过一拍的呢?
FIFO设计多深?
因为本身valid/ready协议是 反压协议 ( 也就是READY_UP为0的时候,不会写FIFO,而不会导致FIFO溢出 )而且此处的读写时钟是同一个时钟,是一个同步FIFO,所以FIFO深度是1或者2就足够了。
深度是1还是2要看极端情况下需要存储几笔数据。
简单分析可以知道,只有一种情况会去向FIFO中存储数据:
- READY_UP是1,可以从upstream接收数据
- 同时READY_DOWN是0,不可以向downstream发送数据
这种情况在极端情况下最多维持多久呢?
答案是: 一个周期 。
因为如果cycle a 时:READY_DOWN=0,那么cycle a+1时,READY_UP变为0了,开始反压,所以只用存一个数就够了。
所以设计为一个深度为1的FIFO就可以了。
深度为1的FIFO有很多特点,设计起来比较简单。比如:wr_ptr/rd_ptr始终指向地址0,所以我们可以删掉wr_ptr和rd_ptr,因为是一个常值0。
简单的depth-1 FIFO实现
使用depth-1 FIFO传输数据,可以这样设计:
这解决了READY打拍的问题。但是这里有一些可以改进的地方,比如:
- 是不是可以挤掉多于的气泡?
- 在FIFO为空的时候,数据是不是可以直接bypass FIFO?
无气泡传输
具体的说,就是既然你这里有个深度为1的FIFO了,那么我是不是可以利用起来,放点数据啊……
当READY_DOWN持续是0的时候,READY_UP依然可以有一个cycle去接收一笔数据,把FIFO资源利用起来:
同样的原因,在RESET情况下,READY_UP可以为1,可以将复位值修改。
那么FIFO穿越呢?
FIFO穿越
考虑一个特殊情况(case 2):
假设READY_DOWN在复位之后始终为1,
然后某个时刻开始VALID_UP为1了。
是不是每个周期,数据都可以直接传下来而不用进入FIFO,即使READY_DOWN打过一拍?
换句话说: ***如果READY_UP=1, READY_DOWN=1, FIFO是空的这种情况下,数据可以直通*** 。
- 上文特殊情况(case 2),READY_DOWN/READY_UP一直是1,显然可以。
- READY_UP从0到1的跳变:READY_DOWN也会在前一周期有一个从0到1的跳变。在READY_DOWN为0时,有一笔数据存到FIFO里边(无气泡传输);当READY_DOWN在时刻a从0变到1时,READY_UP在时刻a+1也会从0变为1。如果此时READY_DOWN也为1,可以直通,不用进入FIFO。也就是:
注意在直通时,我们不希望数据进入FIFO:
将所有这些结合起来:
(注:代码未经详细验证)
换一种思路
经过上面对FIFO的分析,我们可以总结起来,主要是以下几点:
- 加入一个深度为1的同步FIFO,这个FIFO在READY_DOWN为0,且READY_UP为1时暂存一个数据;
- 在READY_DOWN从0->1时,FIFO里边的数据先输出到下级;
- 如果READY_DOWN继续为1,数据可以绕过FIFO直通;
深度为1的FIFO(不管是同步还是异步FIFO),都是一个特殊的逻辑单元。
对于深度为1的同步FIFO,其实就是一拍寄存器打拍。
所以,我们可以这样重新设计:
-
加一级寄存器作为buffer(实际上就是深度为1的FIFO)
-
当以下条件满足,这一级寄存器会暂存一级数据:
2.1 READY_DOWN是0,并且
2.2 READY_UP是1,并且
2.3 VALID_UP是1;
也就是:
- 当READY_UP是1时,数据可以直接暴露在下级接口:READY_UP为1时,BUFFER中一定是空的,因为上一个时钟周期数据已经排空了。也就是:
这其实就是上面的FIFO直通模式。同样我们可以挤掉气泡:
把这所有的总结起来:
(注:代码未经详细验证)
其他
- 我在电脑上简单跑了两个波形,FIFO方法和Buffer方法结果是一样的。
- 用FIFO去隔离开上下两个interface思考,比较容易想明白。
- 无气泡传输、FIFO直通这两个小feature拿掉,也可以工作、也是能实现READY_DOWN时序优化的设计目标的。
-
寄存器
+关注
关注
31文章
5290浏览量
119792 -
AXI总线
+关注
关注
0文章
66浏览量
14244 -
FIFO存储
+关注
关注
0文章
103浏览量
5955
发布评论请先 登录
相关推荐
评论