SignalGenerator.scala 1.88 KB
Newer Older
1
package chisel.miscutils
2
3
import  chisel3._
import  chisel3.util._
4
5

object SignalGenerator {
6
7
8
9
10
11
12
13
14
15
16
  sealed case class Signal(value: Boolean, periods: Int = 1) extends Ordered[Signal] {
    import scala.math.Ordered.orderingToOrdered
    def compare(that: Signal): Int = periods compare that.periods
    def unary_! = this.copy(value = !value)
  }
  final case class Waveform(signals: Seq[Signal]) {
    require (signals.length > 0, "waveform must not be empty")
  }
  implicit def waveformToSeq(w: Waveform): Seq[Signal] = w.signals
  implicit def seqToWaveform(s: Seq[Signal]): Waveform = Waveform.apply(s)

17
18
  implicit def makeSignal(sd: (Boolean, Int)): Signal = Signal(sd._1, sd._2)
  implicit def makeWaveform(ls: List[(Boolean, Int)]): Waveform = ls map makeSignal
19
20
21
22
23

  class IO extends Bundle {
    val v = Output(Bool())
    val in = Input(Bool())
  }
24
25
}

26
27
class SignalGenerator(val signals: SignalGenerator.Waveform,
                      val useInputAsClock: Boolean = false) extends Module {
28
29
30
  require (signals.length > 0, "Waveform must not be empty.")
  require (signals map (_.periods > 1) reduce (_&&_),
      "All signals must have at least two clock cycles length.")
31
  val io = IO(new SignalGenerator.IO)
32
33
  val cnts_rom = Vec(signals map (n => (n.periods - 1).U))
  val vals_rom = Vec(signals map (n => (n.value).B))
34
35
36
  val cnt      = RegInit(UInt(log2Ceil(signals.max.periods).W), init = cnts_rom(0))
  val curr_idx = RegInit(UInt(log2Ceil(signals.length).W), init = 0.U)
  val vreg     = RegInit(Bool(), init = vals_rom(0))
37
38
39

  io.v := vreg

40
41
42
43
44
45
46
47
48
49
  vreg := vals_rom(curr_idx)
  // trigger on either clock or pos input edge
  when (if (useInputAsClock) io.in && !RegNext(io.in) else true.B) {
    when (cnt === 0.U) {
      val next_idx = Mux(curr_idx < (signals.length - 1).U, curr_idx + 1.U, 0.U)
      curr_idx    := next_idx
      cnt         := cnts_rom(next_idx)
    }
    .otherwise {
      cnt := cnt - 1.U
50
51
52
    }
  }
}