FifoAxiAdapter.scala 3.51 KB
Newer Older
1
package chisel.axiutils
Jens Korinth's avatar
Jens Korinth committed
2
3
4
5
6
import Chisel._
import AXIDefs._

class FifoAxiAdapterIO(addrWidth: Int, dataWidth: Int, idWidth: Int) extends Bundle {
  val maxi = new AXIMasterIF(addrWidth, dataWidth, idWidth)
7
  val enq = Decoupled(UInt(width = dataWidth)).flip()
Jens Korinth's avatar
Jens Korinth committed
8
9
10
  val base = UInt(INPUT, width = addrWidth)
}

11
12
class FifoAxiAdapter(fifoDepth: Int,
                     addrWidth: Int,
Jens Korinth's avatar
Jens Korinth committed
13
                     dataWidth: Int,
14
15
16
                     idWidth: Int = 1,
                     burstSize: Option[Int] = None,
                     size: Option[Int] = None) extends Module {
Jens Korinth's avatar
Jens Korinth committed
17

18
  val bsz = burstSize.getOrElse(fifoDepth)
19

20
21
22
23
24
  require (size.map(s => log2Up(s) <= addrWidth).getOrElse(true),
           "addrWidth (%d) must be large enough to address all %d element, at least %d bits"
           .format(addrWidth, size.get, log2Up(size.get)))
  require (size.isEmpty,
           "size parameter is not implemented")
25
26
  require (bsz > 0 && bsz <= fifoDepth && bsz <= 256,
           "burst size (%d) must be 0 < bsz <= FIFO depth (%d) <= 256"
27
           .format(bsz, fifoDepth))
Jens Korinth's avatar
Jens Korinth committed
28

29
30
31
32
  println ("FifoAxiAdapter: fifoDepth = %d, address bits = %d, data bits = %d, id bits = %d%s%s"
           .format(fifoDepth, addrWidth, dataWidth, idWidth,
                   burstSize.map(", burst size = %d".format(_)).getOrElse(""),
                   size.map(", size = %d".format(_)).getOrElse("")))
Jens Korinth's avatar
Jens Korinth committed
33

34
  val io = new FifoAxiAdapterIO(addrWidth, dataWidth, idWidth)
Jens Korinth's avatar
Jens Korinth committed
35

36
37
38
39
  val fifo = Module(new Queue(UInt(width = dataWidth), fifoDepth))
  val axi_write :: axi_wait :: Nil = Enum(UInt(), 2)
  val state = Reg(init = axi_wait)
  val len = Reg(UInt(width = log2Up(bsz)))
40
  val maxi_wlast = state === axi_write && len === UInt(0)
41
  val maxi_waddr = Reg(init = io.base)
42
  val maxi_wavalid = !reset && fifo.io.count >= UInt(bsz)
43
44
45
  val maxi_waready = io.maxi.writeAddr.ready
  val maxi_wready = state === axi_write && io.maxi.writeData.ready
  val maxi_wvalid = state === axi_write && fifo.io.deq.valid
Jens Korinth's avatar
Jens Korinth committed
46

47
48
49
50
51
52
  io.enq                       <> fifo.io.enq
  io.maxi.writeData.bits.last  := maxi_wlast
  io.maxi.writeData.bits.data  := fifo.io.deq.bits
  io.maxi.writeData.valid      := maxi_wvalid
  io.maxi.writeAddr.valid      := maxi_wavalid
  fifo.io.deq.ready            := state === axi_write && io.maxi.writeData.ready
Jens Korinth's avatar
Jens Korinth committed
53

54
55
56
57
58
59
60
61
62
63
  // AXI boilerplate
  io.maxi.writeAddr.bits.addr  := maxi_waddr
  io.maxi.writeAddr.bits.size  := UInt(if (dataWidth > 8) log2Up(dataWidth / 8) else 0)
  io.maxi.writeAddr.bits.len   := UInt(bsz - 1)
  io.maxi.writeAddr.bits.burst := UInt("b01") // INCR
  io.maxi.writeAddr.bits.id    := UInt(0)
  io.maxi.writeAddr.bits.lock  := UInt(0)
  io.maxi.writeAddr.bits.cache := UInt("b1110") // write-through, RW allocate
  io.maxi.writeAddr.bits.prot  := UInt(0)
  io.maxi.writeAddr.bits.qos   := UInt(0)
Jens Korinth's avatar
Jens Korinth committed
64
  io.maxi.writeData.bits.strb  := UInt("b" + ("1" * (dataWidth / 8)))
65
  io.maxi.writeResp.ready      := UInt(1) // ignore responses
Jens Korinth's avatar
Jens Korinth committed
66

67
68
69
  // read channel tie-offs
  io.maxi.readAddr.valid       := Bool(false)
  io.maxi.readData.ready       := Bool(false)
Jens Korinth's avatar
Jens Korinth committed
70
71

  when (reset) {
72
    state := axi_wait
73
    len   := UInt(bsz - 1)
Jens Korinth's avatar
Jens Korinth committed
74
75
  }
  .otherwise {
76
77
78
79
    when (state === axi_wait && fifo.io.count >= UInt(bsz)) { state := axi_write }
      when (maxi_wavalid && maxi_waready) {
        maxi_waddr := maxi_waddr + UInt(bsz * (dataWidth / 8))
      }
80
    when (state === axi_write) {
81
      when (maxi_wready && maxi_wvalid) {
82
83
84
85
        when (maxi_wlast) {
          state := Mux(fifo.io.count >= UInt(bsz), state, axi_wait)
          len := UInt(bsz - 1)
        }
86
87
        .otherwise { len := len - UInt(1) }
      }
Jens Korinth's avatar
Jens Korinth committed
88
89
90
    }
  }
}