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

Jens Korinth's avatar
Jens Korinth committed
6
7
8
9
10
class FifoAxiAdapterIO(fifoDepth: Int)(implicit axi: Configuration) extends Bundle {
  val maxi  = Master(axi)
  val enq   = Flipped(Decoupled(UInt(axi.dataWidth)))
  val base  = Input(UInt(axi.addrWidth))
  val count = Output(UInt(log2Ceil(fifoDepth).W))
Jens Korinth's avatar
Jens Korinth committed
11
12
}

13
14
class FifoAxiAdapter(fifoDepth: Int,
                     burstSize: Option[Int] = None,
Jens Korinth's avatar
Jens Korinth committed
15
16
                     size: Option[Int] = None)
                    (implicit axi: Configuration) extends Module {
Jens Korinth's avatar
Jens Korinth committed
17

Jens Korinth's avatar
Jens Korinth committed
18
  val bsz = burstSize getOrElse fifoDepth
19

Jens Korinth's avatar
Jens Korinth committed
20
21
22
  require (size.map(s => log2Ceil(s) <= axi.addrWidth).getOrElse(true),
           "addrWidth (%d) must be large enough to address all %d elements, at least %d bits"
           .format(axi.addrWidth:Int, size.get, log2Ceil(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
  println ("FifoAxiAdapter: fifoDepth = %d, address bits = %d, data bits = %d, id bits = %d%s%s"
Jens Korinth's avatar
Jens Korinth committed
28
           .format(fifoDepth, axi.addrWidth:Int, axi.dataWidth:Int, axi.idWidth:Int,
29
30
                   burstSize.map(", burst size = %d".format(_)).getOrElse(""),
                   size.map(", size = %d".format(_)).getOrElse("")))
Jens Korinth's avatar
Jens Korinth committed
31

Jens Korinth's avatar
Jens Korinth committed
32
  val io = IO(new FifoAxiAdapterIO(fifoDepth))
Jens Korinth's avatar
Jens Korinth committed
33

Jens Korinth's avatar
Jens Korinth committed
34
  val axi_write :: axi_wait :: Nil = Enum(2)
Jens Korinth's avatar
Jens Korinth committed
35

Jens Korinth's avatar
Jens Korinth committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  val fifo                     = Module(new Queue(UInt(axi.dataWidth), fifoDepth))
  val state                    = RegInit(axi_wait)
  val len                      = Reg(UInt(log2Ceil(bsz).W))
  val maxi_wlast               = state === axi_write && len === 0.U
  val maxi_waddr               = RegInit(io.base)
  val maxi_wavalid             = !reset && fifo.io.count >= bsz.U
  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

  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
  io.count                           := fifo.io.count
Jens Korinth's avatar
Jens Korinth committed
53

54
  // AXI boilerplate
Jens Korinth's avatar
Jens Korinth committed
55
56
57
58
59
60
61
62
63
64
65
  io.maxi.writeAddr.bits.addr        := maxi_waddr
  io.maxi.writeAddr.bits.burst.size  := (if (axi.dataWidth > 8) log2Ceil(axi.dataWidth / 8) else 0).U
  io.maxi.writeAddr.bits.burst.len   := (bsz - 1).U
  io.maxi.writeAddr.bits.burst.burst := Burst.Type.incr
  io.maxi.writeAddr.bits.id          := 0.U
  io.maxi.writeAddr.bits.lock.lock   := 0.U
  io.maxi.writeAddr.bits.cache.cache := Cache.Write.WRITE_THROUGH_RW_ALLOCATE
  io.maxi.writeAddr.bits.prot.prot   := 0.U
  io.maxi.writeAddr.bits.qos         := 0.U
  io.maxi.writeData.bits.strb.strb   := ("b" + ("1" * (axi.dataWidth / 8))).U
  io.maxi.writeResp.ready            := 1.U // ignore responses
Jens Korinth's avatar
Jens Korinth committed
66

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

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