SpinalHDL中AXI Stream连接StreamFifo报层级违规问题求解
报错原因
这个层级违规错误的核心诱因是toBitStream()的调用方式不对:SpinalHDL里Axi4Stream的toBitStream()方法每次调用都会新生成一个独立的Stream硬件节点,不会和之前调用生成的节点复用。你写io.axis_m.toBitStream() << fifo.io.pop的时候,连接符左侧是一个刚创建就被丢弃的临时对象,fifo的pop信号根本没连到顶层的io.axis_m物理端口上——顶层axis_m的valid、payload输出找不到驱动,ready输入信号的驱动路径也断在临时节点上,SpinalHDL做连接合法性检查的时候直接就抛错了。
另外你代码里还有个隐藏的位宽不匹配问题:你定义的AXI Stream端口是32位宽,toBitStream()生成的Stream payload位宽和AXI端口一致是32bit,但实例化的StreamFifo是256bit位宽,就算解决了临时节点的问题,直接连也会报位宽不匹配的错。
修复方法
- 不要在
<<连接符的位置临时调用toBitStream(),把转换得到的Stream节点赋值给固定的val变量持有,确保所有连接都落在真实存在的硬件节点上,不会被编译器回收。 - 根据业务需求匹配两端位宽:
- 如果不需要做位宽转换,直接把FIFO的数据位宽改成和AXI端口一致的32bit就行
- 如果确实需要用256bit的FIFO做缓存,就在AXI端口和FIFO之间插入Stream位宽转换组件,32位输入攒成256位写FIFO,FIFO读出的256位拆成32位输出即可。
参考实现代码
版本1:FIFO与AXI端口位宽一致(32bit)
case class AxiWithFifo() extends Component { val io = new Bundle { val axis_s = slave(Axi4Stream(Axi4StreamConfig(dataWidth = 32))) val axis_m = master(Axi4Stream(Axi4StreamConfig(dataWidth = 32))) } val fifo = StreamFifo(dataType = Bits(32 bits), depth = 128) // 持有转换后的Stream节点,避免生成临时节点 val sBitStream = io.axis_s.toBitStream() val mBitStream = io.axis_m.toBitStream() fifo.io.push << sBitStream mBitStream << fifo.io.pop }
版本2:保留256bit FIFO,增加位宽转换
import spinal.lib._ case class AxiWithFifo() extends Component { val io = new Bundle { val axis_s = slave(Axi4Stream(Axi4StreamConfig(dataWidth = 32))) val axis_m = master(Axi4Stream(Axi4StreamConfig(dataWidth = 32))) } val fifo = StreamFifo(dataType = Bits(256 bits), depth = 128) val sBitStream = io.axis_s.toBitStream() val mBitStream = io.axis_m.toBitStream() // 32bit转256bit写入FIFO val inWidthConv = StreamWidthConverter(32, 256) inWidthConv.io.input << sBitStream fifo.io.push << inWidthConv.io.output // 256bit转32bit输出到AXI主接口 val outWidthConv = StreamWidthConverter(256, 32) outWidthConv.io.input << fifo.io.pop mBitStream << outWidthConv.io.output }
内容的提问来源于stack exchange,提问作者ato1337
相关产品推荐
相关产品推荐

