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 XSDebug(in.ar.fire, 66 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 XSDebug(in.aw.fire, 71 p"[aw] addr: ${Hexadecimal(in.aw.bits.addr)} " + 72 p"awlen:${in.aw.bits.len} awsize:${in.aw.bits.size} " + 73 p"id: ${in.aw.bits.id}\n" 74 ) 75 XSDebug(in.w.fire, 76 p"[w] wmask: ${Binary(in.w.bits.strb)} last:${in.w.bits.last} data:${Hexadecimal(in.w.bits.data)}\n" 77 ) 78 XSDebug(in.b.fire, 79 p"[b] id: ${in.b.bits.id}\n" 80 ) 81 XSDebug(in.r.fire, 82 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