| // Copyright 2024 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package peripheral | |
| import chisel3._ | |
| import chisel3.util._ | |
| import bus._ | |
| import common._ | |
| /** Get a 32-bit AxiMasterReadIO that returns values from a read map. | |
| * @param idBits The bit-width of the id field in the AXI Interface. | |
| * @param reads A map of read names to a (address, value) pair. | |
| */ | |
| object ConnectAxiRead { | |
| def apply(idBits: Integer, | |
| reads: Map[String, (Int, UInt)]): AxiMasterReadIO = { | |
| val axiRead = Wire(Flipped(new AxiMasterReadIO(32, 32, idBits))) | |
| val readReq = Queue(axiRead.addr, 1, pipe=true) | |
| val readResp = readReq.map{req => | |
| val resp = Wire(new AxiReadData(32, idBits)) | |
| val regRead = MuxLookup(req.addr, MakeInvalid(UInt(32.W)))( | |
| reads.values.map{case (a, b) => (a.U(32.W) -> MakeValid(b))}.toSeq | |
| ) | |
| resp.id := req.id | |
| resp.data := regRead.bits | |
| resp.resp := Mux(regRead.valid, 0.U(2.W), "b10".asUInt(2.W)) | |
| resp.last := true.B | |
| resp | |
| } | |
| axiRead.data <> readResp | |
| axiRead | |
| } | |
| } | |
| /** Reads a 32-bit AxiMasterWriteIO and returns the value it tries to write. | |
| * @param idBits The bit-width of the id field in the AXI Interface. | |
| * @param reads A map of write names to target address. | |
| * Returns a map of names->written as well as the data written. | |
| */ | |
| object ConnectAxiWrite { | |
| def apply(idBits: Integer, | |
| writeMap: Map[String, Int], | |
| axiWrite: AxiMasterWriteIO): (Map[String, Bool], UInt) = { | |
| val writeAddrReq = Queue(axiWrite.addr, 1, true /*pipe*/) | |
| val writeDataReq = Queue(axiWrite.data, 1, true /*pipe*/) | |
| // Wait for both queues to be full before removing elements from them | |
| writeAddrReq.ready := writeDataReq.valid && axiWrite.resp.ready | |
| writeDataReq.ready := writeAddrReq.valid && axiWrite.resp.ready | |
| axiWrite.resp.valid := writeDataReq.valid && writeAddrReq.valid | |
| val writeAddr = writeAddrReq.bits.addr | |
| val writeData = writeDataReq.bits.data | |
| val writes = writeMap.mapValues(_.U(32.W) === writeAddr) | |
| axiWrite.resp.bits.id := writeAddrReq.bits.id | |
| axiWrite.resp.bits.resp := Mux(writes.values.toSeq.reduce(_||_), | |
| 0.U(2.W), "b10".asUInt(2.W)) | |
| (writes.toMap, writeData) | |
| } | |
| } |