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