Я не уверен, какова ваша цель зацикливания.Но рассмотрим следующий пример кода (с некоторыми опущенными деталями).В этом примере содержимое RingBuffer предоставляется в виде представления Vec с допустимыми элементами ViewLength.Я думаю, что это демонстрирует скромно элегантный метод для этого определения зацикливания, испускаемое аппаратное обеспечение (или идея представления) может быть не элегантным.Дайте мне знать, если вы не совсем поняли идею цикличности.
import chisel3._
import chisel3.util.log2Ceil
/**
* This ring buffer presents its current contents through view
*
* @param depth
* @param bitWidth
*/
class RingBuffer(depth: Int, bitWidth: Int) extends MultiIOModule {
/*
You need a bunch of IO's here to push and pop and get full status
*/
val view = IO(Output(Vec(depth, UInt(bitWidth.W))))
val viewLength = IO(Output(UInt(log2Ceil(depth).W)))
val data = Reg(Vec(depth, Bool()))
val head = RegInit(0.U(bitWidth.W))
val tail = RegInit(0.U(bitWidth.W))
/* Need some code here to push and pop elements */
// this constructs a mapping between the indices between current head and tail
// to the 0 to n indices of the view
def mappedIndex(i: Int): UInt = {
val out = Wire(UInt(log2Ceil(depth).W))
when((i.U + head) >= depth.U) {
i.U + head
}.otherwise {
(i.U + head) - depth.U
}
out
}
// This creates the complicated Mux structure to map betweem
// the ring buffer elements and 0 to n style view
view.zipWithIndex.foreach { case (viewElement, index) =>
viewElement := data(mappedIndex(index))
}
// This presents the number of valid elements in the current view
val difference = tail - head
when((difference) < 0.U) {
viewLength := (difference) + depth.U
}.otherwise {
viewLength := (difference)
}
}