Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception connecting Vec of IO

Tags:

chisel

Can anyone explain what the problem with this construction is? I have a child module with a Vec of IO that I'm trying to attach to the equivilent IO in the parent module.

This works out fine with just a Seq but I get an exception during elaboration when wrapped up in Vec. The Vec is needed since in my real case that gets indexed with a hardware signal in the child module.

The error:

[error] chisel3.internal.ChiselException: Connection between left (MyBundle[3](Wire in Lower)) and source (MyBundle[3](Wire in Upper)) failed @(0).out: Left or Right unavailable to current module.

The code:

package Testcase

import chisel3._
import chisel3.util._
import chisel3.stage.ChiselStage

import amba._

class MyBundle extends Bundle {
  val out = Output(UInt(32.W))
}

class Upper (n : Int) extends RawModule {
  val io = VecInit(Seq.fill(n)(IO(new MyBundle)))
  val lower = Module(new Lower(n))

  // This should word in the Vec case but gets the same error
  // lower.io <> io

  // This works for non Vec case
  (lower.io, io).zipped map (_ <> _)
}


class Lower (n : Int) extends RawModule {
  val io = VecInit(Seq.fill(n)(IO(new MyBundle)))

  for (i <- 0 to n - 1) {
    io(i).out := 0.U
  }
}

object VerilogMain extends App {
  (new ChiselStage).emitVerilog(new Upper(3), Array("--target-dir", "generated"))
}
like image 375
Brian Magnuson Avatar asked Dec 31 '25 07:12

Brian Magnuson


1 Answers

The issue here is that VecInit creates a Wire of type Vec and connects everything in the Seq to the elements of that Wire. What you're basically doing is creating a Seq of IOs and then connecting them to a Wire.

This is mentioned in the error message (eg. (MyBundle[3](Wire in Lower))) but I totally see the confusion--it's not all that clear and VecInit is probably misnamed. This particular ambiguity in the API comes from historical design decisions in Chisel that are slowly getting fixed but it is a wart that sometimes bites users, sorry about that.

Here's the right way to accomplish what you want, just using IO(Vec(<n>, <type>)). Vec(<n>, <type>) is the way to create something of type Vec, in this case an IO of type Vec, as opposed to creating a Wire and connecting all of the fields:

class Upper (n : Int) extends RawModule {
  //val io = VecInit(Seq.fill(n)(IO(new MyBundle)))
  val io = IO(Vec(n, new MyBundle))
  val lower = Module(new Lower(n))

  // This should word in the Vec case but gets the same error
  lower.io <> io
  
}


class Lower (n : Int) extends RawModule {
  //val io = VecInit(Seq.fill(n)(IO(new MyBundle)))
  val io = IO(Vec(n, new MyBundle))

  for (i <- 0 to n - 1) {
    io(i).out := 0.U
  }
}

(Scastie link: https://scastie.scala-lang.org/COb88oXGRmKQb7BZ3id9gg)

like image 197
Jack Koenig Avatar answered Jan 06 '26 08:01

Jack Koenig



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!