FifoAxiAdapter.scala 3.62 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
  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)))
23
24
  require (bsz > 0 && bsz <= fifoDepth && bsz <= 256,
           "burst size (%d) must be 0 < bsz <= FIFO depth (%d) <= 256"
25
           .format(bsz, fifoDepth))
Jens Korinth's avatar
Jens Korinth committed
26

27
28
29
30
  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
31

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

34
35
36
37
  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)))
38
  val maxi_wlast = state === axi_write && len === UInt(0)
39
  val maxi_waddr = Reg(init = io.base)
40
  val maxi_wavalid = !reset && fifo.io.count >= UInt(bsz)
41
42
43
  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
44

45
46
47
48
49
50
  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
51

52
53
54
55
56
57
58
59
60
61
  // 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
62
  io.maxi.writeData.bits.strb  := UInt("b" + ("1" * (dataWidth / 8)))
63
  io.maxi.writeResp.ready      := UInt(1) // ignore responses
Jens Korinth's avatar
Jens Korinth committed
64

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

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