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

6
7
8
9
10
11
12
object FifoAxiAdapter {
  class IO(fifoDepth: Int)(implicit axi: Axi4.Configuration) extends Bundle {
    val maxi  = Axi4.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
13
14
}

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

Jens Korinth's avatar
Jens Korinth committed
20
  val bsz = burstSize getOrElse fifoDepth
21

Jens Korinth's avatar
Jens Korinth committed
22
23
24
  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)))
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
  println ("FifoAxiAdapter: fifoDepth = %d, address bits = %d, data bits = %d, id bits = %d%s%s"
Jens Korinth's avatar
Jens Korinth committed
30
           .format(fifoDepth, axi.addrWidth:Int, axi.dataWidth:Int, axi.idWidth:Int,
31
32
                   burstSize.map(", burst size = %d".format(_)).getOrElse(""),
                   size.map(", size = %d".format(_)).getOrElse("")))
Jens Korinth's avatar
Jens Korinth committed
33

34
  val io = IO(new FifoAxiAdapter.IO(fifoDepth))
Jens Korinth's avatar
Jens Korinth committed
35

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

Jens Korinth's avatar
Jens Korinth committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  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
55

56
  // AXI boilerplate
Jens Korinth's avatar
Jens Korinth committed
57
58
59
  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
60
  io.maxi.writeAddr.bits.burst.burst := Axi4.Burst.Type.incr
Jens Korinth's avatar
Jens Korinth committed
61
62
  io.maxi.writeAddr.bits.id          := 0.U
  io.maxi.writeAddr.bits.lock.lock   := 0.U
63
  io.maxi.writeAddr.bits.cache.cache := Axi4.Cache.Write.WRITE_THROUGH_RW_ALLOCATE
Jens Korinth's avatar
Jens Korinth committed
64
65
66
67
  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
68

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

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