xref: /XiangShan/src/main/scala/device/AXI4SlaveModule.scala (revision 8891a219bbc84f568e1d134854d8d5ed86d6d560)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package device
18
19import chisel3._
20import chisel3.util._
21import utils._
22import utility._
23import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType, TransferSizes}
24import org.chipsalliance.cde.config.Parameters
25import freechips.rocketchip.amba.axi4.{AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters}
26
27abstract class AXI4SlaveModule[T <: Data]
28(
29  address: Seq[AddressSet],
30  executable: Boolean = true,
31  beatBytes: Int = 8,
32  burstLen: Int = 1,
33  val _extra: T = null
34)(implicit p: Parameters) extends LazyModule {
35
36  val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
37    Seq(AXI4SlaveParameters(
38      address,
39      regionType = RegionType.UNCACHED,
40      executable = executable,
41      supportsWrite = TransferSizes(1, beatBytes * burstLen),
42      supportsRead = TransferSizes(1, beatBytes * burstLen),
43      interleavedId = Some(0)
44    )),
45    beatBytes = beatBytes
46  )))
47
48  lazy val module = new AXI4SlaveModuleImp[T](this)
49
50}
51
52class AXI4SlaveModuleImp[T<:Data](outer: AXI4SlaveModule[T])
53  extends LazyModuleImp(outer)
54{
55  val io = IO(new Bundle {
56    val extra = if(outer._extra == null) None else Some(outer._extra.cloneType)
57  })
58
59  val (in, edge) = outer.node.in.head
60  // do not let MMIO AXI signals optimized out
61  chisel3.dontTouch(in)
62
63
64//  val timer = GTimer()
65  when(in.ar.fire){
66    XSDebug(p"[ar] addr: ${Hexadecimal(in.ar.bits.addr)} " +
67      p"arlen:${in.ar.bits.len} arsize:${in.ar.bits.size} " +
68      p"id: ${in.ar.bits.id}\n"
69    )
70  }
71  when(in.aw.fire){
72    XSDebug(p"[aw] addr: ${Hexadecimal(in.aw.bits.addr)} " +
73      p"awlen:${in.aw.bits.len} awsize:${in.aw.bits.size} " +
74      p"id: ${in.aw.bits.id}\n"
75    )
76  }
77  when(in.w.fire){
78    XSDebug(p"[w] wmask: ${Binary(in.w.bits.strb)} last:${in.w.bits.last} data:${Hexadecimal(in.w.bits.data)}\n")
79  }
80  when(in.b.fire){
81    XSDebug(p"[b] id: ${in.b.bits.id}\n")
82  }
83  when(in.r.fire){
84    XSDebug(p"[r] id: ${in.r.bits.id} data: ${Hexadecimal(in.r.bits.data)}\n")
85  }
86
87  when(in.aw.fire){
88    assert(in.aw.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
89  }
90  when(in.ar.fire){
91    assert(in.ar.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
92  }
93
94  val s_idle :: s_rdata :: s_wdata :: s_wresp :: Nil = Enum(4)
95
96  val state = RegInit(s_idle)
97
98  switch(state){
99    is(s_idle){
100      when(in.ar.fire){
101        state := s_rdata
102      }
103      when(in.aw.fire){
104        state := s_wdata
105      }
106    }
107    is(s_rdata){
108      when(in.r.fire && in.r.bits.last){
109        state := s_idle
110      }
111    }
112    is(s_wdata){
113      when(in.w.fire && in.w.bits.last){
114        state := s_wresp
115      }
116    }
117    is(s_wresp){
118      when(in.b.fire){
119        state := s_idle
120      }
121    }
122  }
123
124
125  val fullMask = MaskExpand(in.w.bits.strb)
126
127  def genWdata(originData: UInt) = (originData & (~fullMask).asUInt) | (in.w.bits.data & fullMask)
128
129  val raddr = Wire(UInt())
130  val (readBeatCnt, rLast) = {
131    val c = Counter(256)
132    val len = HoldUnless(in.ar.bits.len, in.ar.fire)
133    raddr := HoldUnless(in.ar.bits.addr, in.ar.fire)
134    in.r.bits.last := (c.value === len)
135
136    when(in.r.fire) {
137      c.inc()
138      when(in.r.bits.last) {
139        c.value := 0.U
140      }
141    }
142    when(in.ar.fire) {
143      assert(
144        in.ar.bits.len === 0.U ||
145          in.ar.bits.len === 1.U ||
146          in.ar.bits.len === 3.U ||
147          in.ar.bits.len === 7.U ||
148          in.ar.bits.len === 15.U
149      )
150    }
151    (c.value, in.r.bits.last)
152  }
153
154  in.ar.ready := state === s_idle
155  in.r.bits.resp := AXI4Parameters.RESP_OKAY
156  in.r.valid := state === s_rdata
157
158
159  val waddr = Wire(UInt())
160  val (writeBeatCnt, wLast) = {
161    val c = Counter(256)
162    waddr := HoldUnless(in.aw.bits.addr, in.aw.fire)
163    when(in.w.fire) {
164      c.inc()
165      when(in.w.bits.last) {
166        c.value := 0.U
167      }
168    }
169    (c.value, in.w.bits.last)
170  }
171
172  in.aw.ready := state === s_idle && !in.ar.valid
173  in.w.ready := state === s_wdata
174
175  in.b.bits.resp := AXI4Parameters.RESP_OKAY
176  in.b.valid := state===s_wresp
177
178  in.b.bits.id := RegEnable(in.aw.bits.id, in.aw.fire)
179  in.b.bits.user := RegEnable(in.aw.bits.user, in.aw.fire)
180  in.r.bits.id := RegEnable(in.ar.bits.id, in.ar.fire)
181  in.r.bits.user := RegEnable(in.ar.bits.user, in.ar.fire)
182}
183