DecoupledDataSource.scala 1.81 KB
Newer Older
1
package chisel.miscutils
2
3
import  chisel3._
import  chisel3.util._
4

5
object DecoupledDataSource {
6
  /** Interface for DecoupledDataSource. */
7
8
9
  class IO[T <: Data](gen: T) extends Bundle {
    val out = Decoupled(gen.cloneType)
  }
10
11
}

12
13
14
15
16
17
18
19
20
/** Data source providing fixed data via Decoupled interface.
 *  Provides the data given via Decoupled handshakes; if repeat
 *  is true, data is wrapped around.
 *  @param gen Type.
 *  @param size Total number of elements.
 *  @param data Function providing data for each index
 *  @param repeat If true, will always have data via wrap-around,
 *                otherwise valid will go low after data was
 *                consumed.
21
 **/
22
23
24
25
class DecoupledDataSource[T <: Data](gen: T,
                                     val size : Int,
                                     val data: (Int) => T,
                                     val repeat: Boolean = true)
26
                                    (implicit l: Logging.Level) extends Module with Logging {
27
28
  cinfo("size = %d, repeat = %s, addrWidth = %d".format(size,
    if (repeat) "true" else "false", log2Ceil(if (repeat) size else size + 1)))
29
30

  val ds  = for (i <- 0 until size) yield data(i) // evaluate data to array
31
  val io  = IO(new DecoupledDataSource.IO(gen)) // interface
32
  val i   = RegInit(UInt(log2Ceil(if (repeat) size else size + 1).W), 0.U) // index
33
  val rom = Vec.tabulate(size)(n => ds(n)) // ROM with data
34

35
  io.out.bits  := rom(i) // current index data
36
  io.out.valid := repeat.B | i < size.U // valid until exceeded
37

38
  when (io.out.fire()) {
39
40
41
42
43
44
45
    val next = if (repeat) {
      if (math.pow(2, log2Ceil(size)).toInt == size)
        i + 1.U
      else
        Mux((i + 1.U) < size.U, i + 1.U, 0.U)
    } else {
      Mux(i < size.U, i + 1.U, i)
46
    }
47
48
49

    info(p"i = $i -> $next, bits = 0x${Hexadecimal(io.out.bits.asUInt())}")
    i := next
50
51
  }
}