You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Chisel实现2选1多路选择器生成Verilog时遇错误求助

解决Chisel实现AXI多路选择器时的方向冲突错误

错误根源

报错提示Node cannot be analog and must be passive本质是Bundle方向不匹配:

  • AXIIN定义的所有信号都是Input类型,属于被动接收的节点
  • io.out是Flipped(new AXIIN),意味着它的所有信号都是Output方向,需要被主动驱动
  • 直接将Input方向的io.in(i)赋值给Output方向的io.out,会导致被动节点试图驱动主动节点的冲突

解决方案

方案一:使用无方向Bundle定义(推荐)

先定义不带方向的AXI信号Bundle,再在IO端口声明时明确指定方向,从根源避免方向混淆:

import chisel3._
import chisel3.util._

// 定义无方向的AXI信号Bundle
class AXIINBundle extends Bundle {
  val arvalid = Bool()
  val araddr  = UInt(32.W)
  val rready  = Bool()
  val awaddr  = UInt(32.W)
  val awvalid = Bool()
  val wdata   = UInt(32.W)
  val wstrb   = UInt(8.W)
  val wvalid  = Bool()
  val bready  = Bool()
}

class MasterOutMuxIO(nr_m: Int) extends Bundle {
  val in = Vec(nr_m, Input(new AXIINBundle)) // 输入端口:指定为Input
  val selector = Input(UInt(nr_m.W)) // 独热码选择器
  val out = Output(new AXIINBundle) // 输出端口:指定为Output
}

class MasterOutMux(nr_m: Int) extends Module {
  val io = IO(new MasterOutMuxIO(nr_m))
  
  // 直接用MuxLookup选择输入信号驱动输出
  io.out := MuxLookup(io.selector, io.in.last)(
    (0 until nr_m).map(i => ((1.U << i) -> io.in(i)))
  )
}

方案二:适配原有Bundle定义

如果无法修改原AXIIN定义,可手动提取输入信号到Wire(主动节点),再驱动输出:

import chisel3._
import chisel3.util._

class AXIIN extends Bundle {
  val arvalid = Input(Bool())
  val araddr  = Input(UInt(32.W))
  val rready  = Input(Bool())
  val awaddr  = Input(UInt(32.W))
  val awvalid = Input(Bool())
  val wdata   = Input(UInt(32.W))
  val wstrb   = UInt(8.W)
  val wvalid  = Input(Bool())
  val bready  = Input(Bool())
}

class MasterOutMuxIO(nr_m: Int) extends Bundle {
  val in = Vec(nr_m, new AXIIN)
  val selector = Input(UInt(nr_m.W))
  val out = Flipped(new AXIIN)
}

class MasterOutMux(nr_m: Int) extends Module {
  val io = IO(new MasterOutMuxIO(nr_m))
  
  // 将每个输入Bundle的信号提取到Wire
  val inWires = io.in.map { in =>
    val wire = Wire(new AXIIN)
    wire.arvalid := in.arvalid
    wire.araddr := in.araddr
    wire.rready := in.rready
    wire.awaddr := in.awaddr
    wire.awvalid := in.awvalid
    wire.wdata := in.wdata
    wire.wstrb := in.wstrb
    wire.wvalid := in.wvalid
    wire.bready := in.bready
    wire
  }
  
  // 用Wire做多路选择
  val selected = MuxLookup(io.selector, inWires.last)(
    (0 until nr_m).map(i => ((1.U << i) -> inWires(i)))
  )
  
  // 驱动输出端口
  io.out.arvalid := selected.arvalid
  io.out.araddr := selected.araddr
  io.out.rready := selected.rready
  io.out.awaddr := selected.awaddr
  io.out.awvalid := selected.awvalid
  io.out.wdata := selected.wdata
  io.out.wstrb := selected.wstrb
  io.out.wvalid := selected.wvalid
  io.out.bready := selected.bready
}

关键说明

Chisel中不能直接用Input方向的信号驱动Output端口,Input是被动接收的节点,必须通过Wire这类主动节点中转后才能作为驱动源。方案一的无方向Bundle定义是Chisel的最佳实践,能有效避免方向相关的错误。

内容的提问来源于stack exchange,提问作者Amadeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:41:14