使用For循环展开设计过滤器



我正在尝试使用Chisel创建一个可合成FIR滤波器。我正在从csv文件中读取有符号整数,然后将其作为系数传递给FIR滤波器类。只是为了给大家一个味道-这就是系数的样子:

-152651856 1233223 ...

然后使用for循环在滤波器的系数上进行MAC操作。我找不到for循环没有正确展开的原因。它只是将最后一个系数合成为一个常数。

class FIR (val coefficients:Array[Int], val count:Int ) extends Module {
  val io = IO(new Bundle {
    val X        = Input(Vec(count,SInt(16.W)))
    val Y_out     = Output(SInt(64.W))
  })
  val sum  = Reg(SInt(64.W))
  sum := 0.S(64.W)
  val temp = Reg(Vec(count,SInt(64.W)))

  for(ct <- 0 until count ) {
   temp(ct) := new  fromIntToLiteral(coefficients(ct): Int).S
   sum := sum + temp(ct) * io.X(ct)
  }
  io.Y_out := sum
}

这里,数组coefficients是传递到类的滤波器的系数,而count是系数的数目。

需要记住的重要一点是Chisel是而不是行为合成。没有阻塞分配(尽管可以模拟(。Chisel具有最后连接语义,因此最后连接获胜。这在以后的连接被断言(即由when保护(时非常有用,但也可以用于覆盖默认值。

要查看发生了什么,让我们为count选择一个值并展开循环:

// Let count = 4
temp(0) := new  fromIntToLiteral(coefficients(0): Int).S                        
sum := sum + temp(0) * io.X(0)
temp(1) := new  fromIntToLiteral(coefficients(1): Int).S
sum := sum + temp(1) * io.X(1)
temp(2) := new  fromIntToLiteral(coefficients(2): Int).S
sum := sum + temp(2) * io.X(2)
temp(3) := new  fromIntToLiteral(coefficients(3): Int).S
sum := sum + temp(3) * io.X(3)

最后一次连接使其与相同

temp(0) := new  fromIntToLiteral(coefficients(0): Int).S                        
// sum := sum + temp(0) * io.X(0)
temp(1) := new  fromIntToLiteral(coefficients(1): Int).S
// sum := sum + temp(1) * io.X(1)
temp(2) := new  fromIntToLiteral(coefficients(2): Int).S
// sum := sum + temp(2) * io.X(2)
temp(3) := new  fromIntToLiteral(coefficients(3): Int).S
sum := sum + temp(3) * io.X(3) // <--- Winning connect to sum

您可能要做的是在for循环执行时增量创建总和,就像在Verilog中使用阻塞赋值一样。我们可以使用var(我们可以重新分配的变量(来模拟这种行为,以保持中间值:

  val sum  = Reg(SInt(64.W))
  val temp = Reg(Vec(count,SInt(64.W)))
  var sumVar = 0.S(64.W)
  for(ct <- 0 until count ) {
   temp(ct) := coefficients(ct).S
   sumVar = sumVar + temp(ct) * io.X(ct)
  }
  sum := sumVar    // Connect the finished logic to the sum's "next" value.
  io.Y_out := sum  // Connect current value of sum register to output

我想在这里强调几点:

  1. 注意,我们将=用于sumVar,将其视为指向硬件节点的指针。我们正在更新指针,以指向我们在每次迭代中构建的新逻辑

  2. 我可能误解了你的意图,因为我的代码看起来不像我熟悉的FIR(编辑:代码是正确的,请参阅对此答案的评论(。注意,在Chisel中,Reg对应于触发器的实际寄存器或阵列。它不像Verilog reg那样。Reg的描述如下:https://www.chisel-lang.org/chisel3/sequential-circuits.html.你也可以看看Chisel训练营,它使用FIR滤波器作为一个激励性的例子。

  3. 我注意到您直接使用fromIntToLiteral。这是一个隐式类,实际上不应该面向用户。你可以只写coefficients(ct).S,Scala让它在你不注意的情况下工作,只要你写import chisel3._。如果你想知道更多的细节,隐含者是如何在Scala中实现扩展方法的。当您import chisel3._时,.S方法隐含地来自fromIntToLiteral,并使其看起来类似于S是在Int上定义的方法。将其视为语法糖,使Chisel代码更易于编写。

最新更新