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