Проектирование фильтра с использованием scala - для развертывания l oop - PullRequest
3 голосов
/ 08 марта 2020

Я пытаюсь создать синтезируемый FIR-фильтр, используя Chisel. Я читаю целые числа со знаком из CSV-файла, который затем передаю классу FIR-фильтра в качестве коэффициентов. Просто для того, чтобы вы все поняли - вот как выглядит коэффициент:

-152651856 1233223 ...

A для l oop используется для выполнения операции MA C через коэффициенты фильтра. Я не могу найти причину, по которой for l oop не разворачивается должным образом. Он только синтезирует последний коэффициент как константу.

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 - это число коэффициентов.

1 Ответ

2 голосов
/ 08 марта 2020

Важно помнить, что долото является не поведенческим синтезом. Нет назначения блокировки (хотя оно может быть эмулировано). Вместо этого у долота семантика последнего соединения , так что последнее соединение побеждает. Это в первую очередь полезно, когда более поздние подключения предикаты (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

Я хочу выделить несколько вещей здесь:

  1. Обратите внимание, что мы используем = для sumVar, воспринимайте это как указатель на аппаратный узел. Мы обновляем указатель, чтобы он указывал на новую логику c, которую мы построили каждую итерацию

  2. Возможно, я неправильно понял ваше намерение, поскольку мой код не похож на FIR I знаком с (РЕДАКТИРОВАТЬ: код правильный, см. комментарии к этому ответу). Обратите внимание, что в долоте Reg соответствует фактическому, регистру или массиву триггеров. Это не , как Verilog reg. Reg описано здесь: https://www.chisel-lang.org/chisel3/sequential-circuits.html. Вы также можете взглянуть на Chisel Bootcamp , в котором в качестве мотивирующего примера используются КИХ-фильтры.

  3. Я заметил, что вы непосредственно используете fromIntToLiteral. Это неявный класс , который на самом деле не предназначен для пользователя. Вы можете просто написать coefficients(ct).S, Scala, чтобы вы работали без вашего уведомления, если вы делаете import chisel3._. Если вы хотите узнать больше деталей, подразумевается, как можно реализовать Методы расширения в Scala. Когда вы import chisel3._, метод .S происходит из fromIntToLiteral неявным образом и делает его похожим на S, определенный в Int. Думайте об этом как о синтактике c, чтобы сделать код долота более удобным для написания.

...