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