ProgrammableMaster.scala 3.67 KB
Newer Older
Jens Korinth's avatar
Jens Korinth committed
1
package chisel.axi.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
13
14
15
16
17
18
19
20
21
22
23
24
25
sealed abstract trait MasterAction {
  def isRead: Boolean
  def address: Int
  def value: Option[BigInt]
}

final case class MasterRead(address: Int) extends MasterAction {
  def isRead: Boolean = true
  def value: Option[BigInt] = None
}

final case class MasterWrite(address: Int, v: BigInt) extends MasterAction {
  def isRead: Boolean = false
  def value: Option[BigInt] = Some(v)
}
26

Jens Korinth's avatar
Jens Korinth committed
27
28
29
30
/** 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.
31
 **/
Jens Korinth's avatar
Jens Korinth committed
32
33
class ProgrammableMaster(action: Seq[MasterAction])
                        (implicit axi: Axi4Lite.Configuration) extends Module {
Jens Korinth's avatar
Jens Korinth committed
34
35
36
37
  val io = IO(new Bundle {
    val maxi     = Axi4Lite.Master(axi)
    val out      = Decoupled(UInt(axi.dataWidth))
    val finished = Output(Bool())
38
    val w_resp   = Irrevocable(new chisel.axi.Axi4Lite.WriteResponse)
Jens Korinth's avatar
Jens Korinth committed
39
  })
40

41
  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
42
43
44
  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))
45
46
  val r_data = RegNext(io.maxi.readData.bits.data)

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

Jens Korinth's avatar
Jens Korinth committed
49
  q.io.enq.valid                 := false.B
50
51
52
53
54
55
  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
56
57
  io.maxi.readAddr.valid         := false.B
  io.maxi.writeAddr.valid        := false.B
58

Jens Korinth's avatar
Jens Korinth committed
59
60
  io.maxi.readAddr.bits.addr     := 0.U
  io.maxi.writeAddr.bits.addr    := 0.U
61
62

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

Jens Korinth's avatar
Jens Korinth committed
65
  io.finished                    := cnt === action.length.U
66

67
68
69
  // always assign address from current action
  for (i <- 0 until action.length) {
    when (i.U === cnt) {
70
71
      io.maxi.readAddr.bits.addr  := action(i).address.U
      io.maxi.writeAddr.bits.addr := action(i).address.U
72
    }
73
  }
74
75

  when (state === s_addr) {
76
    for (i <- 0 until action.length) {
Jens Korinth's avatar
Jens Korinth committed
77
      when (i.U === cnt) {
78
79
80
        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 }
81
82
      }
    }
83
84
85
86
    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      }
  }
87

88
89
90
91
92
93
94
  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
95
96
      }
    }
97
  }
98

99
100
101
102
103
104
  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
105
106
107
      }
    }
  }
108
109

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