在一个时钟周期内多次重新分配变量 - Chisel

Reassign a variable multiple times within a clock cycle - Chisel

我想在单个时钟周期内多次重新分配变量 hit_bits。只要 io.bits_perf.bits(i) 为真,hit_bits 就会增加。当我尝试编译代码时,我得到 "FOUND COMBINATIONAL PATH!"。

有什么想法吗?

  val hit_bits = Bits()
  hit_bits := Bits(0)

  when(io.bits_perf.valid){
    for(i<- 0 until 3){
      when(io.bits_perf.bits(i)) { hit_bits := hit_bits + Bits(1) 
      }
    }
  }

对于这个例子,重要的是要记住 ChiselScala 之间的区别。更具体地说,when 是映射到 Verilog 中的条件连接的 Chisel 结构,而 for 是我们可以用来生成硬件的 Scala 结构(类似于 Verilog 中的 generate)。 =25=]

让我们展开这个 for 循环,看看我们得到了什么:

when(io.bits_perf.valid){
  when(io.bits_perf.bits(0)) { hit_bits := hit_bits + Bits(1) }
  when(io.bits_perf.bits(1)) { hit_bits := hit_bits + Bits(1) }
  when(io.bits_perf.bits(2)) { hit_bits := hit_bits + Bits(1) }
}

请注意,所有连接都是相同的,当 io.bits_perf.valid 为高且 io.bits_perf.bits 中的任何位为高时,您将连接 hit_bitshit_bits + Bits(1).这是组合循环。

现在,让我们弄清楚如何表达您真正想要做的事情:当 io.bits_perf.valid 很高时,如何将 hit_bits 连接到 io.bits_perf.bits 中的个数。这也称为 popcount,Chisel 恰好有一个实用程序。你应该做的是使用:

  val hit_bits = Bits()
  hit_bits := Bits(0)

  when(io.bits_perf.valid) {
    hit_bits := PopCount(io.bits_perf.bits)
  }

但是,您编写的代码几乎是正确的,所以让我们让它正常工作吧。我们想要做的是使用 Scala for 循环来生成一些代码。一种方法是使用 Scala var(允许重新分配)作为对 Chisel 节点的 "pointer" 而不是 val 只允许单一赋值(因此不能更改为指向不同的 Chisel 节点)。

var hit_bits = Bits(0, 2) // We set the width because + does not expand width
when (io.bits_perf.valid) {
  for (i <- 0 until 3) {
    hit_bits = hit_bits + io.bits_perf.bits(i)
  }
}
// Now hit_bits is equal to the popcount of io.bits_perf.bits (or 0 if not valid)

请注意,我在有条件时也删除了内部,因为您可以直接添加位而不是有条件地添加 1。这里发生的是 hit_bits 是对 Chisel 节点的引用,以 0。然后,对于 for 循环中的每个索引,我们将 hit_bits 节点更改为 Chisel 节点,该节点是前一个节点 hit_bits 和 [=17 的一点相加的输出=].