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