Важно помнить, что долото является не поведенческим синтезом. Нет назначения блокировки (хотя оно может быть эмулировано). Вместо этого у долота семантика последнего соединения , так что последнее соединение побеждает. Это в первую очередь полезно, когда более поздние подключения предикаты (ie. Защищены when
), но также могут быть полезны для переопределения значений по умолчанию.
Чтобы увидеть, что происходит, давайте выберем значение для count
и разверните l oop:
// 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
То, что вы, вероятно, пытаетесь сделать, это создавать сумму постепенно, как для l oop выполняется так же, как в 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
, воспринимайте это как указатель на аппаратный узел. Мы обновляем указатель, чтобы он указывал на новую логику c, которую мы построили каждую итерацию
Возможно, я неправильно понял ваше намерение, поскольку мой код не похож на FIR I знаком с (РЕДАКТИРОВАТЬ: код правильный, см. комментарии к этому ответу). Обратите внимание, что в долоте Reg
соответствует фактическому, регистру или массиву триггеров. Это не , как Verilog reg
. Reg
описано здесь: https://www.chisel-lang.org/chisel3/sequential-circuits.html. Вы также можете взглянуть на Chisel Bootcamp , в котором в качестве мотивирующего примера используются КИХ-фильтры.
Я заметил, что вы непосредственно используете fromIntToLiteral
. Это неявный класс , который на самом деле не предназначен для пользователя. Вы можете просто написать coefficients(ct).S
, Scala, чтобы вы работали без вашего уведомления, если вы делаете import chisel3._
. Если вы хотите узнать больше деталей, подразумевается, как можно реализовать Методы расширения в Scala. Когда вы import chisel3._
, метод .S
происходит из fromIntToLiteral
неявным образом и делает его похожим на S
, определенный в Int
. Думайте об этом как о синтактике c, чтобы сделать код долота более удобным для написания.