summaryrefslogtreecommitdiff
path: root/src/test/scala/cookbook/FSM.scala
blob: 40f8abc7b668f46bd2ef28fda1a9526760e0732f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// SPDX-License-Identifier: Apache-2.0

package cookbook

import chisel3._
import chisel3.util._

/* ### How do I create a finite state machine?
 *
 * Use ChiselEnum to construct the states and switch & is to construct the FSM
 * control logic
 */

class DetectTwoOnes extends Module {
  val io = IO(new Bundle {
    val in = Input(Bool())
    val out = Output(Bool())
  })

  object State extends ChiselEnum {
    val sNone, sOne1, sTwo1s = Value
  }

  val state = RegInit(State.sNone)

  io.out := (state === State.sTwo1s)

  switch(state) {
    is(State.sNone) {
      when(io.in) {
        state := State.sOne1
      }
    }
    is(State.sOne1) {
      when(io.in) {
        state := State.sTwo1s
      }.otherwise {
        state := State.sNone
      }
    }
    is(State.sTwo1s) {
      when(!io.in) {
        state := State.sNone
      }
    }
  }
}

class DetectTwoOnesTester extends CookbookTester(10) {

  val dut = Module(new DetectTwoOnes)

  // Inputs and expected results
  val inputs: Vec[Bool] = VecInit(false.B, true.B, false.B, true.B, true.B, true.B, false.B, true.B, true.B, false.B)
  val expected: Vec[Bool] =
    VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B)

  dut.io.in := inputs(cycle)
  assert(dut.io.out === expected(cycle))
}

class FSMSpec extends CookbookSpec {
  "DetectTwoOnes" should "work" in {
    assertTesterPasses { new DetectTwoOnesTester }
  }
}