我正在尝试使用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不是行为综合。没有阻塞分配(尽管可以模拟)。相反,凿子具有最后连接语义,以便最终连接获胜。在断言以后的连接(即由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
我想在这里强调一些事情:
请注意,对于
=
,我们使用sumVar
,将其视为指向硬件节点的指针。我们正在更新指针,以指向我们在每次迭代中构建的新逻辑由于我的代码看起来不像我熟悉的FIR,我可能误解了您的意图(编辑:代码正确,请参见此答案的注释)。注意,在凿子中,
Reg
对应于实际的触发器寄存器或数组。它不像Verilog reg
。 Reg
在这里描述:https://www.chisel-lang.org/chisel3/sequential-circuits.html。您还可以查看Chisel Bootcamp,它始终将FIR滤波器用作激励示例。我注意到您正在直接使用
fromIntToLiteral
。这是一个隐式类,实际上不应该面向用户。您只需编写coefficients(ct).S
,只要您执行import chisel3._
,Scala就可以使它工作而无需您注意。如果您想了解更多细节,隐式就是如何在Scala中实现Extension Methods。当您import chisel3._
时,.S
方法隐式地来自fromIntToLiteral
,使它看起来像S
是在Int
上定义的方法。可以将其视为语法糖,以使Chisel代码更易于编写。