SignalGenerator.scala 1.91 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
19
20
  implicit def makeSignal(sd: (Boolean, Int)): Signal = Signal(sd._1, sd._2)
  implicit def makeWaveform(ls: List[(Boolean, Int)]): Waveform = ls map makeSignal
}

21
22
class SignalGenerator(val signals: SignalGenerator.Waveform,
                      val useInputAsClock: Boolean = false) extends Module {
23
24
25
  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.")
26
27
28
29
30
  val io = IO(new Bundle { val v = Output(Bool()); val in = Input(Bool()) })
  val cnts_rom = Vec(signals map (n => (n.periods - 1).U))
  val vals_rom = Vec(signals map (n => (n.value).B))
  val cnt      = Reg(UInt(log2Ceil(signals.max.periods).W))
  val curr_idx = Reg(UInt(log2Ceil(signals.length).W))
31
32
33
34
35
  val vreg     = Reg(Bool())

  io.v := vreg

  when (reset) {
36
    curr_idx := 0.U
37
    cnt      := cnts_rom(0)
38
    vreg     := vals_rom(0)
39
40
41
42
  }
  .otherwise {
    vreg := vals_rom(curr_idx)
    // trigger on either clock or pos input edge
43
44
45
    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)
46
47
48
49
        curr_idx    := next_idx
        cnt         := cnts_rom(next_idx)
      }
      .otherwise {
50
        cnt := cnt - 1.U
51
52
53
54
      }
    }
  }
}