Есть несколько незначительных проблем с этим кодом:
- Обычно мы называем переменные, начинающиеся со строчной буквы в Scala, это в основном стиль, но он имеет семантическое значение в определенных обстоятельствах(например, сопоставление с образцом)
- Квадратные скобки используются только для параметров типа (например, обобщений Java), при индексировании в Scala используются нормальные скобки
- Входной Vec of Bools обычно определяется как:
val req = Input(Vec(numInputs, Bool()))
(при условии import chisel3._
, но это также должно работать в Chisel._
для долота 3.2) if
и else
используются для статической параметризации (т. е. во время разработки аппаратного обеспечения), тогда как when
и.otherwise
используются для динамической логики (например, фактические муксы) UInt
для типов оборудования, если у вас есть статический параметр (например, numInputs
), используйте Scala Int
Помимо мелких синтаксических вещей, самая хитрая часть правильного понимания этого кода - это понимание различия между конструкциями Scala, которые выполняются только на разработке Тиме (т.е. когда программа Scala генерирует аппаратное обеспечение), по сравнению с тем, что фактически отображается в аппаратном обеспечении. Я бы посоветовал прочитать эту ветку из списка рассылки пользователей зубил для получения дополнительной информации о некоторых вещах: https://groups.google.com/d/msg/chisel-users/gRoNnH-Y5hE/ynDCtmNPCAAJ
Я немного запутался относительно того, какое значение io.grant
должно получить,но я предполагаю, что это должен быть индекс с самым высоким приоритетом io.req
. Вот непроверенная версия вашего кода, которую я считаю должен работать и делать то, что вы хотите:
//Priority Encoder
class P_Encoder(numInputs: Int) extends Module {
// We wrap ports in IO
val io = IO(new Bundle {
val req = Input(Vec(numInputs, Bool()))
val rls = Input(Vec(numInputs, Bool()))
val grant = Output(UInt(log2Up(numInputs).W))
})
io.grant := 0.U // default grant value
// Due to Chisel last connect semantics, the last connection wins
// Thus the highest index will have priority
for (i <- 0 to numInputs - 1) {
when (io.req(i) && !io.rls(i)) {
io.grant := i.U
}
}
}
Этот код хитрый, потому что он смешивает цикл разработки for
с оборудованием when
s и соединения, я собираюсь вручную развернуть этот цикл, чтобы проиллюстрировать, что он делает:
io.grant := 0.U
when (io.req(0) && !io.rls(0)) {
io.grant := 0.U
}
when (io.req(1) && !io.rls(1)) {
io.grant := 1.U
}
when (io.req(2) && !io.rls(2)) {
io.grant := 2.U
}
...
В качестве альтернативы, мы можем просто повторно использовать встроенную утилиту PriorityEncoder, если нам нужно
import chisel3.util.PriorityEncoder
val enables = io.req.zip(io.rls).map { case (x, y) => x && !y }
// PriorityEncoder gives priority to *lowest* order bit
io.grant := PriorityEncoder(enables)