AxiFifoAdapter.scala 5.23 KB
Newer Older
Jens Korinth's avatar
Jens Korinth committed
1
package chisel.axi.axi4
2
3
import  chisel.axi._
import  chisel.miscutils.Logging
Jens Korinth's avatar
Jens Korinth committed
4
5
import  chisel3._
import  chisel3.util._
6

7
object AxiFifoAdapter {
Jens Korinth's avatar
Jens Korinth committed
8
9
10
11
12
  /** Configuration parameters for AxiFifoAdapter.
   *  @param axi AXI-MM interface parameters.
   *  @param fifoDepth Depth of the backing FIFO (each element data width wide).
   *  @param burstSize Number of beats per burst (optional).
   *  @param size Address wrap-around after size elements (optional).
13
14
15
16
   **/
  sealed case class Configuration(fifoDepth: Int,
                                  burstSize: Option[Int] = None,
                                  size: Option[Int] = None)
17

Jens Korinth's avatar
Jens Korinth committed
18
  /** I/O bundle for AxiFifoAdapter. */
19
  class IO(cfg: Configuration)(implicit axi: Axi4.Configuration) extends Bundle {
Jens Korinth's avatar
Jens Korinth committed
20
21
22
23
    val enable = Input(Bool())
    val maxi   = Axi4.Master(axi)
    val deq    = Decoupled(UInt(axi.dataWidth))
    val base   = Input(UInt(axi.addrWidth))
24
25
  }

Jens Korinth's avatar
Jens Korinth committed
26
27
28
  /** Build an AxiFifoAdapter.
   *  @param cfg Configuration.
   *  @return AxiFifoAdapter instance.
29
30
31
32
   **/
  def apply(cfg: Configuration)(implicit axi: Axi4.Configuration, l: Logging.Level): AxiFifoAdapter =
    new AxiFifoAdapter(cfg)

Jens Korinth's avatar
Jens Korinth committed
33
34
35
36
37
  /** Build an AxiFifoAdapter.
   *  @param fifoDepth Depth of the backing FIFO (each element data width wide).
   *  @param burstSize Number of beats per burst (optional).
   *  @param size Address wrap-around after size elements (optional).
   *  @return AxiFifoAdapter instance.
38
39
40
41
42
43
   **/
  def apply(fifoDepth: Int,
            burstSize: Option[Int] = None,
            size: Option[Int] = None)
           (implicit axi: Axi4.Configuration, l: Logging.Level): AxiFifoAdapter =
    new AxiFifoAdapter(Configuration(fifoDepth = fifoDepth, burstSize = burstSize, size = size))
44
}
Jens Korinth's avatar
Jens Korinth committed
45

Jens Korinth's avatar
Jens Korinth committed
46
47
48
49
/** AxiFifoAdapter is simple DMA engine filling a FIFO via AXI-MM master.
 *  The backing FIFO is filled continuosly with bursts via the master
 *  interface; the FIFO itself uses handshakes for consumption.
 *  @param cfg Configuration parameters.
50
 **/
51
52
53
class AxiFifoAdapter(cfg: AxiFifoAdapter.Configuration)
                    (implicit axi: Axi4.Configuration,
                     logLevel: Logging.Level) extends Module with Logging{
54
  val bsz = cfg.burstSize.getOrElse(cfg.fifoDepth)
Jens Korinth's avatar
Jens Korinth committed
55

Jens Korinth's avatar
Jens Korinth committed
56
57
58
  require (cfg.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, cfg.size.get, log2Ceil(cfg.size.get)))
59
  require (cfg.size.isEmpty,
Jens Korinth's avatar
Jens Korinth committed
60
           "size parameter is not implemented")
61
  require (bsz > 0 && bsz <= cfg.fifoDepth && bsz <= 256,
Jens Korinth's avatar
Jens Korinth committed
62
           "burst size (%d) must be 0 < bsz <= FIFO depth (%d) <= 256"
63
           .format(bsz, cfg.fifoDepth))
Jens Korinth's avatar
Jens Korinth committed
64

65
66
67
68
  cinfo ("AxiFifoAdapter: fifoDepth = %d, address bits = %d, data bits = %d, id bits = %d%s%s"
         .format(cfg.fifoDepth, axi.addrWidth:Int, axi.dataWidth:Int, axi.idWidth:Int,
                 cfg.burstSize.map(", burst size = %d".format(_)).getOrElse(""),
                 cfg.size.map(", size = %d".format(_)).getOrElse("")))
Jens Korinth's avatar
Jens Korinth committed
69

70
  val io = IO(new AxiFifoAdapter.IO(cfg))
Jens Korinth's avatar
Jens Korinth committed
71
  val en = RegNext(io.enable, init = false.B)
Jens Korinth's avatar
Jens Korinth committed
72

Jens Korinth's avatar
Jens Korinth committed
73
74
  val axi_read :: axi_wait :: Nil = Enum(2)

Jens Korinth's avatar
Jens Korinth committed
75

Jens Korinth's avatar
Jens Korinth committed
76
77
  val fifo  = Module(new Queue(UInt(axi.dataWidth), cfg.fifoDepth))
  val state = RegInit(axi_wait)
Jens Korinth's avatar
Jens Korinth committed
78
79
  val len   = RegInit(UInt(log2Ceil(bsz).W), (bsz - 1).U)
  val ra_hs = RegInit(Bool(), init = false.B)
80

Jens Korinth's avatar
Jens Korinth committed
81
82
  val maxi_rlast   = io.maxi.readData.bits.last
  val maxi_raddr   = RegInit(io.base)
Jens Korinth's avatar
Jens Korinth committed
83
  val maxi_ravalid = state === axi_read & ~ra_hs
Jens Korinth's avatar
Jens Korinth committed
84
  val maxi_raready = io.maxi.readAddr.ready
Jens Korinth's avatar
Jens Korinth committed
85
86
  val maxi_rready  = state === axi_read & fifo.io.enq.ready
  val maxi_rvalid  = state === axi_read & io.maxi.readData.valid
Jens Korinth's avatar
Jens Korinth committed
87

Jens Korinth's avatar
Jens Korinth committed
88
89
90
91
92
  io.deq                            <> fifo.io.deq
  fifo.io.enq.bits                  := io.maxi.readData.bits.data
  io.maxi.readData.ready            := maxi_rready
  io.maxi.readAddr.valid            := maxi_ravalid
  fifo.io.enq.valid                 := io.maxi.readData.valid
Jens Korinth's avatar
Jens Korinth committed
93
94

  // AXI boilerplate
95
96
97
98
  io.maxi.readAddr.bits.defaults
  io.maxi.writeAddr.bits.defaults
  io.maxi.writeData.bits.defaults

Jens Korinth's avatar
Jens Korinth committed
99
100
101
102
103
104
105
106
107
  io.maxi.readAddr.bits.addr        := maxi_raddr
  io.maxi.readAddr.bits.burst.size  := (if (axi.dataWidth > 8) log2Ceil(axi.dataWidth / 8) else 0).U
  io.maxi.readAddr.bits.burst.len   := (bsz - 1).U
  io.maxi.readAddr.bits.burst.burst := Axi4.Burst.Type.incr
  io.maxi.readAddr.bits.id          := 0.U
  io.maxi.readAddr.bits.lock.lock   := 0.U
  io.maxi.readAddr.bits.cache.cache := Axi4.Cache.Read.WRITE_BACK_RW_ALLOCATE
  io.maxi.readAddr.bits.prot.prot   := 0.U
  io.maxi.readAddr.bits.qos         := 0.U
Jens Korinth's avatar
Jens Korinth committed
108
109

  // write channel tie-offs
Jens Korinth's avatar
Jens Korinth committed
110
111
112
  io.maxi.writeAddr.valid           := false.B
  io.maxi.writeData.valid           := false.B
  io.maxi.writeResp.ready           := false.B
113

Jens Korinth's avatar
Jens Korinth committed
114
115
  when (en) {
    when (state === axi_wait & fifo.io.count <= (cfg.fifoDepth - bsz).U) { state := axi_read }
Jens Korinth's avatar
Jens Korinth committed
116
    when (state === axi_read) {
Jens Korinth's avatar
Jens Korinth committed
117
      when (maxi_ravalid & maxi_raready) {
Jens Korinth's avatar
Jens Korinth committed
118
119
        maxi_raddr := maxi_raddr + (bsz * (axi.dataWidth / 8)).U
        ra_hs := true.B
120
      }
Jens Korinth's avatar
Jens Korinth committed
121
      when (maxi_rready & maxi_rvalid) {
Jens Korinth's avatar
Jens Korinth committed
122
        when (maxi_rlast) {
Jens Korinth's avatar
Jens Korinth committed
123
124
125
          state := Mux(fifo.io.count <= (cfg.fifoDepth - bsz).U, state, axi_wait)
          len := (bsz - 1).U
          ra_hs := false.B
Jens Korinth's avatar
Jens Korinth committed
126
        }
Jens Korinth's avatar
Jens Korinth committed
127
        .otherwise { len := len - 1.U }
128
129
130
131
      }
    }
  }
}