xref: /XiangShan/src/main/scala/device/AXI4SlaveModule.scala (revision a2e9bde6390a265b32b8c01575d8193a7197e0eb)
1package device
2
3import chisel3._
4import chisel3.util._
5import utils._
6import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType, TransferSizes}
7import chipsalliance.rocketchip.config.Parameters
8import freechips.rocketchip.amba.axi4.{AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters}
9import xiangshan.HasXSLog
10
11abstract class AXI4SlaveModule[T <: Data]
12(
13  address: Seq[AddressSet],
14  executable: Boolean = true,
15  beatBytes: Int = 8,
16  burstLen: Int = 1,
17  val _extra: T = null
18)(implicit p: Parameters) extends LazyModule {
19
20  val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
21    Seq(AXI4SlaveParameters(
22      address,
23      regionType = RegionType.UNCACHED,
24      executable = executable,
25      supportsWrite = TransferSizes(1, beatBytes * burstLen),
26      supportsRead = TransferSizes(1, beatBytes * burstLen),
27      interleavedId = Some(0)
28    )),
29    beatBytes = beatBytes
30  )))
31
32  lazy val module = new AXI4SlaveModuleImp[T](this)
33
34}
35
36class AXI4SlaveModuleImp[T<:Data](outer: AXI4SlaveModule[T])
37  extends LazyModuleImp(outer) with HasXSLog
38{
39  val io = IO(new Bundle {
40    val extra = if(outer._extra == null) None else Some(outer._extra.cloneType)
41  })
42
43  val (in, edge) = outer.node.in.head
44
45//  val timer = GTimer()
46  when(in.ar.fire()){
47    XSDebug(p"[ar] addr: ${Hexadecimal(in.ar.bits.addr)} " +
48      p"arlen:${in.ar.bits.len} arsize:${in.ar.bits.size} " +
49      p"id: ${in.ar.bits.id}\n"
50    )
51  }
52  when(in.aw.fire()){
53    XSDebug(p"[aw] addr: ${Hexadecimal(in.aw.bits.addr)} " +
54      p"awlen:${in.aw.bits.len} awsize:${in.aw.bits.size} " +
55      p"id: ${in.aw.bits.id}\n"
56    )
57  }
58  when(in.w.fire()){
59    XSDebug(p"[w] wmask: ${Binary(in.w.bits.strb)} last:${in.w.bits.last} data:${Hexadecimal(in.w.bits.data)}\n")
60  }
61  when(in.b.fire()){
62    XSDebug(p"[b] id: ${in.b.bits.id}\n")
63  }
64  when(in.r.fire()){
65    XSDebug(p"[r] id: ${in.r.bits.id} data: ${Hexadecimal(in.r.bits.data)}\n")
66  }
67
68  when(in.aw.fire()){
69    assert(in.aw.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
70  }
71  when(in.ar.fire()){
72    assert(in.ar.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
73  }
74
75  private val s_idle :: s_rdata :: s_wdata :: s_wresp :: Nil = Enum(4)
76
77  private val state = RegInit(s_idle)
78
79  switch(state){
80    is(s_idle){
81      when(in.ar.fire()){
82        state := s_rdata
83      }
84      when(in.aw.fire()){
85        state := s_wdata
86      }
87    }
88    is(s_rdata){
89      when(in.r.fire() && in.r.bits.last){
90        state := s_idle
91      }
92    }
93    is(s_wdata){
94      when(in.w.fire() && in.w.bits.last){
95        state := s_wresp
96      }
97    }
98    is(s_wresp){
99      when(in.b.fire()){
100        state := s_idle
101      }
102    }
103  }
104
105
106  val fullMask = MaskExpand(in.w.bits.strb)
107
108  def genWdata(originData: UInt) = (originData & (~fullMask).asUInt()) | (in.w.bits.data & fullMask)
109
110  val raddr = Wire(UInt())
111  val (readBeatCnt, rLast) = {
112    val c = Counter(256)
113    val len = HoldUnless(in.ar.bits.len, in.ar.fire())
114    raddr := HoldUnless(in.ar.bits.addr, in.ar.fire())
115    in.r.bits.last := (c.value === len)
116
117    when(in.r.fire()) {
118      c.inc()
119      when(in.r.bits.last) {
120        c.value := 0.U
121      }
122    }
123    when(in.ar.fire()) {
124      assert(
125        in.ar.bits.len === 0.U ||
126          in.ar.bits.len === 1.U ||
127          in.ar.bits.len === 3.U ||
128          in.ar.bits.len === 7.U ||
129          in.ar.bits.len === 15.U
130      )
131    }
132    (c.value, in.r.bits.last)
133  }
134
135  in.ar.ready := state === s_idle
136  in.r.bits.resp := AXI4Parameters.RESP_OKAY
137  in.r.valid := state === s_rdata
138
139
140  val waddr = Wire(UInt())
141  val (writeBeatCnt, wLast) = {
142    val c = Counter(256)
143    waddr := HoldUnless(in.aw.bits.addr, in.aw.fire())
144    when(in.w.fire()) {
145      c.inc()
146      when(in.w.bits.last) {
147        c.value := 0.U
148      }
149    }
150    (c.value, in.w.bits.last)
151  }
152
153  in.aw.ready := state === s_idle
154  in.w.ready := state === s_wdata
155
156  in.b.bits.resp := AXI4Parameters.RESP_OKAY
157  in.b.valid := state===s_wresp
158
159  in.b.bits.id := RegEnable(in.aw.bits.id, in.aw.fire())
160  in.b.bits.user := RegEnable(in.aw.bits.user, in.aw.fire())
161  in.r.bits.id := RegEnable(in.ar.bits.id, in.ar.fire())
162  in.r.bits.user := RegEnable(in.ar.bits.user, in.ar.fire())
163}
164