使用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
相关产品推荐
相关产品推荐

