在SpinalHDL的世界里,它基于core提供了丰富的Lib库,包含了Stream、Flow、Fragment、State Machine、Bus Slave Factory等一系列强大的使用库,从而让HDL的世界能够像普通软件语言一样进行扩展。
考虑下图
电路逻辑:

上图中电路有四组接口:

memWrite为Flow接口(valid+payload),用于对Ram进行写操作,cmdA为Stream接口(valid+ready+payload),用于对Ram进行读操作,cmdB、rsp均为Stream接口,当cmdA、cmdB同时到达时,rsp输出cmdA读出的Ram内的值与cmdB负载(payload)进行异或输出,采用Stream协议(valid+ready)。
乍看,意兴阑珊
上图中的逻辑按照功能划分基本可分为两大基础部分:
Ram读写逻辑:接收memWrite的写指令,将数据写入ram;接收cmdA的读指令,并将读取出的数据按照Stream协议进行封装产生cmdA_rdata
Join逻辑:等待cmdA、cmdB同时有效时异或产生rsp输出逻辑,并处理Stream握手协议。
电路功能很小,逻辑亦很清晰,用Verilog来写亦不是难事,这里用SpinalHDL手写该逻辑电路如下:

功能很简单,但我们也需要按照Stream协议规范处理接口握手信号及每一个电路细节,稍有不慎就需要我们
仿真一会儿~
再回首,别有洞天
再看这个逻辑电路图,所有的接口包括逻辑模块之间的电路都可以抽象为Stream接口或Lib接口,而SpinalHDL针对Stream、Flow提供了丰富的Lib库,借助库函数,可以非常方便的实现上述电路逻辑:

在上面的代码中,14~18行例化了一个Mem并实现其写端口逻辑,20行通过Mem提供的streamReadSync函数实现对Mem的读操作(接收一个Stream总线作为读请求,payload做读地址,valid做读使能,读取的结果赋值给一个Stream接口),第21行StreamJoin函数接收两个Stream接口作为参数,等待两个Stream接口均有效时输出rsp Stream valid,并将数据进行translateWith(memReadStream.payload ^ io.cmdB.payload)替换。
在上述代码中,核心代码只有20~21行,通过对Lib的调用,我们能够快速的构建描述电路,而其生成的同样也是RTL可读代码,但大大减少了调试的时间。
写在最后
无论SpinalHDL也好还是传统的Verilog也好,其本质仍需要我们有逻辑设计的思维,但SpinalHDL为我们提供了一个能够像写软件的方式去实现硬件,条条大路通罗马,最近的或许是最好的,至于诸君或喜或厌,那就萝卜白菜,各有所爱了。
原作者:玉骐