使用Rocket Chip生成AXI4Crossbar报错及定制参数方案咨询
问题分析与解决方案
报错原因定位
从错误栈的根因可以看出,报错发生在AXI4SlaveParameters初始化阶段,核心是require断言失败。问题出在**TransferSizes的用法**:
Rocket Chip中,AXI4SlaveParameters的supportsWrite/supportsRead参数接收的TransferSizes表示支持的burst长度(以beat为单位),虽然AXI4协议允许burst长度为1~256,但直接使用TransferSizes(64)这种单值写法在部分版本的Rocket Chip中会触发断言失败。此外,空的axi4Driver和axi4Accept模块不会导致初始化错误,但生成Verilog时会出现警告。
修复后的完整代码
package empty import chipsalliance.rocketchip.config.{Config, Parameters} import chisel3._ import chisel3.stage.ChiselStage import freechips.rocketchip.diplomacy._ import freechips.rocketchip.amba.axi4._ object myAxiUtil{ val myAXI4MasterParameters = AXI4MasterParameters(name="Axi4Master", id=IdRange(0,3)) val myAXI4MasterPortParameters = Seq(AXI4MasterPortParameters(masters=Seq(myAXI4MasterParameters))) // 修正TransferSizes为支持1~64的burst长度 val myAXI4SlaveParameters1 = AXI4SlaveParameters( address = Seq(AddressSet(0x80000000L, 0xffff)), supportsWrite = TransferSizes(1, 64), supportsRead = TransferSizes(1, 64) ) val myAXI4SlavePortParameters1 = Seq(AXI4SlavePortParameters(slaves=Seq(myAXI4SlaveParameters1), beatBytes=64)) val myAXI4SlaveParameters2 = AXI4SlaveParameters( address = Seq(AddressSet(0x90000000L, 0xffff)), supportsWrite = TransferSizes(1, 64), supportsRead = TransferSizes(1, 64) ) val myAXI4SlavePortParameters2 = Seq(AXI4SlavePortParameters(slaves=Seq(myAXI4SlaveParameters2), beatBytes=64)) val myAXI4SlaveParameters3 = AXI4SlaveParameters( address = Seq(AddressSet(0x00000000L, 0xffffffff)), supportsWrite = TransferSizes(1, 64), supportsRead = TransferSizes(1, 64) ) val myAXI4SlavePortParameters3 = Seq(AXI4SlavePortParameters(slaves=Seq(myAXI4SlaveParameters3), beatBytes=64)) } // 添加dummy逻辑避免空模块警告 class axi4Driver()(implicit valName:ValName, p:Parameters) extends LazyModule { import myAxiUtil._ val node = AXI4MasterNode(myAXI4MasterPortParameters) lazy val module = new LazyModuleImp (this) { val (out, _) = node.out(0) // 初始化AXI4信号为默认值 out.aw.valid := false.B out.aw.bits := DontCare out.w.valid := false.B out.w.bits := DontCare out.b.ready := false.B out.ar.valid := false.B out.ar.bits := DontCare out.r.ready := false.B } override lazy val desiredName = "axi4Driver" } // 添加dummy响应逻辑 class axi4Accept()(implicit valName:ValName, p:Parameters) extends LazyModule { import myAxiUtil._ val node = AXI4SlaveNode(myAXI4SlavePortParameters3) lazy val module = new LazyModuleImp (this) { val (in, _) = node.in(0) // 对所有请求返回OK响应 in.aw.ready := true.B in.w.ready := true.B in.b.valid := true.B in.b.bits := AXI4BundleResponses.OKAY in.ar.ready := true.B in.r.valid := true.B in.r.bits := AXI4BundleResponses.OKAY in.r.bits.data := 0.U } override lazy val desiredName = "axi4Accept" } class xbarTestHarness()(implicit valName:ValName, p:Parameters) extends LazyModule { import myAxiUtil._ val numSlaves = 2 val drivers = Seq.fill(numSlaves){ LazyModule(new axi4Driver()) } val accept = LazyModule(new axi4Accept()) val xbar = AXI4Xbar() // 修正连接语法 accept.node := xbar drivers.foreach { d => xbar := d.node } lazy val module = new LazyModuleImp (this) {} override lazy val desiredName = "xbarTestHarness" } // 自定义AXI参数配置类 class CustomAXIConfig extends Config( new freechips.rocketchip.subsystem.WithAXI4AddrWidth(64) ++ new freechips.rocketchip.subsystem.WithAXI4DataWidth(512) ++ new chipsalliance.rocketchip.config.BaseConfig ) object AxiMain extends App { println("Generating Hardware") // 使用自定义配置生成硬件 implicit val p = new CustomAXIConfig val verilog = (new ChiselStage).emitVerilog(LazyModule(new xbarTestHarness()).module) }
自定义AXI4Crossbar参数(addrWidth、dataWidth)
1. 数据宽度(dataWidth)
通过AXI4MasterPortParameters和AXI4SlavePortParameters中的beatBytes参数控制:
dataWidth = beatBytes * 8,例如beatBytes=64对应512位数据宽度,beatBytes=32对应256位数据宽度。
2. 地址宽度(addrWidth)
- 自动协商:Diplomacy会根据你定义的
AddressSet最大地址范围自动推导地址宽度。 - 强制指定:通过自定义
Config类配置,示例代码中CustomAXIConfig指定了64位地址宽度和512位数据宽度,主函数中使用该配置即可生效。
运行sbt run即可生成符合要求的AXI4Crossbar Verilog代码。
内容的提问来源于stack exchange,提问作者xlgforever
相关产品推荐
相关产品推荐

