Chisel for循环实现寄存器赋值,编译时报错

问题遇到的现象和发生背景

Chisel for循环实现寄存器赋值,编译时报错

用代码块功能插入代码,请勿粘贴截图
package CBB_CDC_INTR
import CBB_CDC_L2L._
import chisel3._
import chisel3.util._
import chisel3.util.experimental._
import chisel3.stage.ChiselGeneratorAnnotation

class CBB_CDC_INTR (BIT_WIDTH : Int,SYNC_STAGE: Int,POLARITY: Bool,CNT_WIDTH: Int,EXPAND_CNT: Int) extends Module {
  val io = IO{new Bundle {
    forceName(clock,"src_clk")
    forceName(reset,"src_rst")
    val dst_clk = Input(Clock())
    forceName(dst_clk,"dst_clk")
    val dst_rst = Input(Bool())
    forceName(dst_rst,"dst_rst")
    val din     = Input(UInt(BIT_WIDTH.W))
    forceName(din,"din")
    val dout    = Output(UInt(BIT_WIDTH.W))
    forceName(dout,"dout")
  }}
  val dout_level = Wire(UInt(BIT_WIDTH.W))
  val din_level  = Wire(UInt(BIT_WIDTH.W))
  val neg_polarity = Wire(UInt(1.W))
  val polarity = Wire(UInt(1.W))
  when(POLARITY.asUInt === 1.U) {
    polarity := "b1".U
  }.otherwise {
    polarity := "b0".U
  }
  when(POLARITY.asUInt === 1.U){
    neg_polarity := "b0".U
  }.otherwise{
    neg_polarity := "b1".U
  }
  val NEG_POLARITY = neg_polarity.asBool
  withClockAndReset(io.dst_clk,io.dst_rst){
    val dout_level_1ff = RegNext(dout_level,neg_polarity)
    for (i <- 0 until BIT_WIDTH) {
      io.dout := (dout_level(i) === polarity) && (dout_level_1ff(i) === neg_polarity)
    }
  }
  withClockAndReset(clock, reset){
    val din_level_reg = Reg(UInt(BIT_WIDTH.W))
    val din_cnt       = Reg(Vec(CNT_WIDTH,UInt(BIT_WIDTH.W)))
    for (j <- 0 until BIT_WIDTH) {
      when((io.din(j) === polarity) && (din_level(j) === neg_polarity) && (din_cnt(j) === EXPAND_CNT.asUInt)) {
        din_level_reg(j) := polarity
      }.elsewhen((din_level(j) === polarity) && (din_cnt(j) === EXPAND_CNT.asUInt)) {
        din_level_reg(j) := neg_polarity
      }.otherwise {
        din_level_reg(j) := din_level_reg(j)
      }
      din_level(j) := din_level_reg(j)
    }
      for(k <- 0 until BIT_WIDTH){
        when((din_cnt(k) >= EXPAND_CNT.asUInt) && (din_level_reg(k) === polarity) && (io.din(k) === polarity)){
          din_cnt(k) := 0.U(CNT_WIDTH.W)
        }.elsewhen(din_cnt(k) <= EXPAND_CNT.asUInt){
          din_cnt(k) := din_cnt(k) + 1.U(CNT_WIDTH.W)
        }.otherwise{
          din_cnt(k) := din_cnt(k)
        }
      }
  }

  val U_CBB_CDC_L2L = Module(new CBB_CDC_L2L(BIT_WIDTH,NEG_POLARITY,SYNC_STAGE))
  U_CBB_CDC_L2L.clock := io.dst_clk
  U_CBB_CDC_L2L.reset := io.dst_rst
  U_CBB_CDC_L2L.io.dout := dout_level
  U_CBB_CDC_L2L.io.din  := din_level
}

object CBB_CDC_INTR_Gen extends App{
  (new chisel3.stage.ChiselStage).execute(Array("--target-dir","generated/cbb_cdc_intr"),Seq(ChiselGeneratorAnnotation(() => new CBB_CDC_INTR(16,3,false.B,4,15))))
}

运行结果及报错内容

报错信息为:

Exception in thread "main" chisel3.internal.ChiselException: Cannot reassign to read-only CBB_CDC_INTR.?: OpResult[Bool]
    at ... ()
    at CBB_CDC_INTR.CBB_CDC_INTR.$anonfun$new$23(CBB_CDC_INTR.scala:47)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
    at chisel3.WhenContext.(When.scala:143)
    at chisel3.when$.apply(When.scala:38)
    at CBB_CDC_INTR.CBB_CDC_INTR.$anonfun$new$21(CBB_CDC_INTR.scala:46)
    at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:190)
    at CBB_CDC_INTR.CBB_CDC_INTR.$anonfun$new$16(CBB_CDC_INTR.scala:45)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
    at chisel3.withClockAndReset$.apply(MultiClock.scala:26)
    at CBB_CDC_INTR.CBB_CDC_INTR.(CBB_CDC_INTR.scala:42)
    at CBB_CDC_INTR.CBB_CDC_INTR_Gen$.$anonfun$new$44(CBB_CDC_INTR.scala:74)
    at ... ()
    at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)

Process finished with exit code 1

我想要达到的结果

麻烦帮忙看下究竟是哪里出了问题,谢谢。

ChiselException:无法重新分配给只读

分析,无法将位子集赋给:=左侧的位子集。解决这个问题的一种方法是创建一个Vec的UInt(1.W),然后将其作为RHS作为单个赋值。我认为您的if有问题,我建议使用foldLeft而不是for

参考链接:https://stackoverflow.com/questions/67534935/scala-chisel-ripple-carry-adder-syntax

...

补充例化的另一个模块的代码

package CBB_CDC_L2L
import chisel3._
import chisel3.util._
import chisel3.util.experimental._
import chisel3.stage.ChiselGeneratorAnnotation

class CBB_CDC_L2L(WIDTH : Int,RST_VAL : Bool,SYNC_STAGE: Int) extends Module {
  val io = IO(new Bundle {
    forceName(clock,"clk")
    forceName(reset,"rst")
    val din  = Input(UInt(WIDTH.W))
    forceName(din,"din")
    val dout = Output(UInt(WIDTH.W))
    forceName(dout,"dout")
  })
  withReset(reset.asAsyncReset) {
    val din_dly_nxt = Reg(Vec(SYNC_STAGE, UInt(WIDTH.W)))
    val din_dly = RegNext(din_dly_nxt(SYNC_STAGE-2),RST_VAL.asUInt)
    io.dout := din_dly
    for (i <- 0 until SYNC_STAGE) {
      if (i == 0) {
        din_dly_nxt(0) := io.din
      }
      else {
        din_dly_nxt(i) := din_dly_nxt(i - 1)
      }
      //din_dly := din_dly_nxt(SYNC_STAGE-1)
    }
  }
}

object CBB_CDC_L2L_Gen extends App{
  (new chisel3.stage.ChiselStage).execute(Array("--target-dir","generated/cbb_cdc_l2l"),Seq(ChiselGeneratorAnnotation(() => new CBB_CDC_L2L(16,false.B,3))))
}