ProgrammableMaster.scala 3.46 KB
Newer Older
Jens Korinth's avatar
Jens Korinth committed
1
package chisel.axiutils.axi4lite
Jens Korinth's avatar
Jens Korinth committed
2
3
4
import  chisel3._
import  chisel3.util._
import  chisel.axi._
5

Jens Korinth's avatar
Jens Korinth committed
6
7
8
9
/** AXI4Lite master transaction model.
 *  @param isRead true for read transactions.
 *  @param addr address to read from.
 *  @param value write value (optional)
10
11
12
 **/
case class MasterAction(isRead: Boolean = true, addr: Int, value: Option[BigInt])

Jens Korinth's avatar
Jens Korinth committed
13
14
15
16
/** Axi4LiteProgrammableMaster is a testing tool to perform a sequence of master actions.
 *  It automatically performs simple AXI4Lite transactions on slave.
 *  @param action Sequence of transactions, executed sequentially without delay.
 *  @param axi implicit AXI configuration.
17
 **/
Jens Korinth's avatar
Jens Korinth committed
18
19
class ProgrammableMaster(action: Seq[MasterAction])
                        (implicit axi: Axi4Lite.Configuration) extends Module {
Jens Korinth's avatar
Jens Korinth committed
20
21
22
23
24
25
  val io = IO(new Bundle {
    val maxi     = Axi4Lite.Master(axi)
    val out      = Decoupled(UInt(axi.dataWidth))
    val finished = Output(Bool())
    val w_resp   = Decoupled(UInt(2.W))
  })
26

Jens Korinth's avatar
Jens Korinth committed
27
28
29
30
  val cnt = Reg(UInt(log2Ceil(action.length + 1).W)) // current action; last value indicates completion
  val s_addr :: s_wtransfer :: s_rtransfer :: s_response :: s_idle :: Nil = Enum(5)
  val state = RegInit(s_addr)
  val w_data = Reg(UInt(axi.dataWidth))
31
32
  val r_data = RegNext(io.maxi.readData.bits.data)

Jens Korinth's avatar
Jens Korinth committed
33
  val q = Module(new Queue(UInt(axi.dataWidth), action.length))
34

Jens Korinth's avatar
Jens Korinth committed
35
  q.io.enq.valid                 := false.B
36
37
38
39
40
41
  q.io.enq.bits                  := io.maxi.readData.bits.data
  io.maxi.readData.ready         := q.io.enq.ready
  io.out <> q.io.deq

  io.maxi.writeData.bits.data    := w_data
  io.maxi.writeData.valid        := state === s_wtransfer
Jens Korinth's avatar
Jens Korinth committed
42
43
  io.maxi.readAddr.valid         := false.B
  io.maxi.writeAddr.valid        := false.B
44

Jens Korinth's avatar
Jens Korinth committed
45
46
  io.maxi.readAddr.bits.addr     := 0.U
  io.maxi.writeAddr.bits.addr    := 0.U
47
48

  io.w_resp <> io.maxi.writeResp
Jens Korinth's avatar
Jens Korinth committed
49
  io.maxi.writeResp.ready        := true.B
50

Jens Korinth's avatar
Jens Korinth committed
51
  io.finished                    := cnt === action.length.U
52
53

  when (reset) {
Jens Korinth's avatar
Jens Korinth committed
54
    cnt := 0.U
55
56
57
58
  }
  .otherwise {
    // always assign address from current action
    for (i <- 0 until action.length) {
Jens Korinth's avatar
Jens Korinth committed
59
60
61
      when (i.U === cnt) {
        io.maxi.readAddr.bits.addr  := action(i).addr.U
        io.maxi.writeAddr.bits.addr := action(i).addr.U
62
63
64
65
66
      }
    }

    when (state === s_addr) {
      for (i <- 0 until action.length) {
Jens Korinth's avatar
Jens Korinth committed
67
68
69
70
        when (i.U === cnt) {
          io.maxi.readAddr.valid  := action(i).isRead.B
          io.maxi.writeAddr.valid := (! action(i).isRead).B
          action(i).value map { v => w_data := v.U }
71
72
73
74
        }
      }
      when (io.maxi.readAddr.ready && io.maxi.readAddr.valid)   { state := s_rtransfer }
      when (io.maxi.writeAddr.ready && io.maxi.writeAddr.valid) { state := s_wtransfer }
Jens Korinth's avatar
Jens Korinth committed
75
      when (cnt === action.length.U)                            { state := s_idle      }
76
77
78
79
    }

    when (state === s_rtransfer) {
      for (i <- 0 until action.length) {
Jens Korinth's avatar
Jens Korinth committed
80
81
82
83
        val readReady  = action(i).isRead.B && io.maxi.readData.ready && io.maxi.readData.valid
        when (i.U === cnt && readReady) {
          q.io.enq.valid := io.maxi.readData.bits.resp === 0.U // response OKAY
          cnt := cnt + 1.U
84
85
86
87
88
89
90
          state := s_addr
        }
      }
    }

    when (state === s_wtransfer) {
      for (i <- 0 until action.length) {
Jens Korinth's avatar
Jens Korinth committed
91
92
93
        val writeReady = (!action(i).isRead).B && io.maxi.writeData.ready && io.maxi.writeData.valid
        when (i.U === cnt && writeReady) {
          cnt := cnt + 1.U
94
95
96
97
98
99
100
101
102
          state := s_response
        }
      }
    }

    when (state === s_response && io.maxi.writeResp.valid) { state := s_addr }
  }
}