2016-12-02 7 views
2

Я хотел бы переназначить переменную hit_bits несколько раз за один такт. hit_bits будет увеличен при io.bits_perf.bits(i). Я получаю «НАЙДЕННЫЙ КОМБИНАЦИОННЫЙ ПУТЬ!». когда я пытаюсь скомпилировать код.Переназначить переменную несколько раз в течение тактового цикла - Chisel

Любая идея?

val hit_bits = Bits() 
    hit_bits := Bits(0) 

    when(io.bits_perf.valid){ 
    for(i<- 0 until 3){ 
     when(io.bits_perf.bits(i)) { hit_bits := hit_bits + Bits(1) 
     } 
    } 
    } 

ответ

3

Для этого примера, важно иметь в виду разницу между зубила и Scala. Более конкретно, when представляет собой конструкцию долота, которая сопоставляется с условными соединениями в Verilog, тогда как for является конструкцией Scala, которую мы можем использовать для создания аппаратного обеспечения (аналогично generate в Verilog).

Давайте раскатать этот цикл и посмотрим, что мы получаем:

when(io.bits_perf.valid){ 
    when(io.bits_perf.bits(0)) { hit_bits := hit_bits + Bits(1) } 
    when(io.bits_perf.bits(1)) { hit_bits := hit_bits + Bits(1) } 
    when(io.bits_perf.bits(2)) { hit_bits := hit_bits + Bits(1) } 
} 

Обратите внимание, что все соединения являются такими же, когда io.bits_perf.valid высока, и любой из битов в io.bits_perf.bits высока, вы будете подключать hit_bits - hit_bits + Bits(1). Это комбинационный цикл.

Теперь давайте выясним, как выразить то, что вы действительно пытаетесь сделать: как подключить hit_bits к числу единиц в io.bits_perf.bits, когда io.bits_perf.valid является высоким. Это также известно как popcount, для которого у долота просто так есть утилита. То, что вы должны сделать, это использовать, что:

val hit_bits = Bits() 
    hit_bits := Bits(0) 

    when(io.bits_perf.valid) { 
    hit_bits := PopCount(io.bits_perf.bits) 
    } 

Однако код, который вы написали близко к правильному, так давайте сделаем это работать в любом случае. Мы хотим использовать цикл Scala для создания кода. Один из способов сделать это - использовать Scala var (который позволяет переназначить) как своего рода «указатель» на узлы долота, а не val, который допускает только одно назначение (и, следовательно, его нельзя изменить, чтобы указать на другой узел долота).

var hit_bits = Bits(0, 2) // We set the width because + does not expand width 
when (io.bits_perf.valid) { 
    for (i <- 0 until 3) { 
    hit_bits = hit_bits + io.bits_perf.bits(i) 
    } 
} 
// Now hit_bits is equal to the popcount of io.bits_perf.bits (or 0 if not valid) 

Обратите внимание, что я упал внутренний, когда условно, так как вы можете просто добавить немного напрямую, а не условно добавления 1. То, что происходит здесь в том, что hit_bits является ссылкой на Зубило узлы, начиная с 0. Затем для каждого индекса в цикле for мы меняем узел. Hit_bits означает узел Chizel, который является результатом добавления предыдущего узла hit_bits и бит io.bits_perf.bits.