在SpinalHDL里,其lib库处处可见Stream的身影,而在常用的逻辑设计里,尤其接口的处理中,握手信号的处理也是老生常谈的话题。而在接受设计里,SpinalHDL中的“一别两宽”式设计方式,着实让我赞同。
》》Stream
Stream本质上是一个带数据的握手协议:
在数字逻辑电路里,无论是普通的模块接口之间,还是标准的AMBA、Avalon等总线,都处处可见Stream的身影:
》》握手之殇,纠缠不清
无论是新手还是老手,对于Stream这种握手形式的逻辑处理还是挺烦的。Stream这种握手形式的逻辑仅仅是添加一级寄存器还是颇显得繁琐的,需要小心翼翼的处理。更遑论当设计里还牵涉到数据的处理。这种在处理功能逻辑的同时又要考虑握手信号的处理时在设计逻辑电路时还是显得颇头大的,毕竟“一心二用”还是颇有不便……
仔细想想,在接口信号处理时,功能性的设计往往是组合逻辑颇多,而为了更好的满足时序约束,往往需要添加寄存器来优化时序,单独处理或许并不显得复杂,但当把两者混在一块儿便极易“按起葫芦浮起瓢”,导致设计功能性错误了。 倘若纠缠不清令人头大,那一别两宽呢?把功能逻辑和为了优化时序的pipeline分开岂不是设计极其简单。
》》Stream pipeline
Stream的pipeline处理在SpinalHDL里提供了很好的封装:
Stream接口的pipeline里有三种类型:
m2sPipe: 为两个Stream接口之间的valid,payload之间添加一级寄存器。
s2mPipe:为两个Stream接口之间的ready路径添加一级寄存器。
s2mPipe().m2sPipe():在两个Stream接口之间的valid,payload、ready之间均添加一级寄存器。
上面的三种接口pipeline方式能够很好的满足接口中的时序优化。SpinalHDL里也提供了相应简单的连接符(箭头指向谁谁就是目的端)。关于这里面的源代码分析可参见文章《打个拍,握个手可以么》。
》》功能处理
有了前面Stream接口的pipeline方式,在Stream接口信号中的处理功能性逻辑时,我们便可以采用组合逻辑的方式进行处理。举个简单的例子,在逻辑设计里对输入的Stream信号中的payload如果大于0x80加1输出,小于0x80减1输出。那么这里便可以仅以组合逻辑的形式进行处理:
在上面的逻辑处理里,整个设计均采用组合逻辑的形式进行处理。
》》合二为一
有了上面的那些,那么合二为一便很容易了。功能处理采用组合逻辑,时序处理采用pipeline。“一别两宽”之后,合二为一便好了:
》》写在最后
就个人使用来讲,在SpinalHDL的设计里,这种方式极大的简化了电路设计的复杂度。理解了Stream的使用,那么对于SpinalHDL中lib的大多数功能也能够有一个很好的了解与使用。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !