SignalGenerator.scala 1.96 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
34
35
  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))
36
37
38
39
40
  val vreg     = Reg(Bool())

  io.v := vreg

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