ProgrammableMaster.scala 3.37 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
  val io = IO(new Bundle {
    val maxi     = Axi4Lite.Master(axi)
    val out      = Decoupled(UInt(axi.dataWidth))
    val finished = Output(Bool())
24
    val w_resp   = Irrevocable(new chisel.axi.Axi4Lite.WriteResponse)
Jens Korinth's avatar
Jens Korinth committed
25
  })
26

27
  val cnt = RegInit(UInt(log2Ceil(action.length + 1).W), init = 0.U) // current action; last value indicates completion
Jens Korinth's avatar
Jens Korinth committed
28
29
30
  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
54
55
56
57
58
  // always assign address from current action
  for (i <- 0 until action.length) {
    when (i.U === cnt) {
      io.maxi.readAddr.bits.addr  := action(i).addr.U
      io.maxi.writeAddr.bits.addr := action(i).addr.U
    }
59
  }
60
61

  when (state === s_addr) {
62
    for (i <- 0 until action.length) {
Jens Korinth's avatar
Jens Korinth committed
63
      when (i.U === cnt) {
64
65
66
        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 }
67
68
      }
    }
69
70
71
72
    when (io.maxi.readAddr.ready && io.maxi.readAddr.valid)   { state := s_rtransfer }
    when (io.maxi.writeAddr.ready && io.maxi.writeAddr.valid) { state := s_wtransfer }
    when (cnt === action.length.U)                            { state := s_idle      }
  }
73

74
75
76
77
78
79
80
  when (state === s_rtransfer) {
    for (i <- 0 until action.length) {
      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
        state := s_addr
81
82
      }
    }
83
  }
84

85
86
87
88
89
90
  when (state === s_wtransfer) {
    for (i <- 0 until action.length) {
      val writeReady = (!action(i).isRead).B && io.maxi.writeData.ready && io.maxi.writeData.valid
      when (i.U === cnt && writeReady) {
        cnt := cnt + 1.U
        state := s_response
91
92
93
      }
    }
  }
94
95

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