blob: 51316990c94aeb736ae3fc604c29c1e395d3e75e [file]
/*
Copyright 2024 Google LLC
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.
SPDX-License-Identifier: Apache-2.0
*/
package DMAController.Frontend
import DMAController.Bus._
import DMAController.Worker.{XferDescBundle}
import chisel3._
import chisel3.util._
class TLULReader(val addrWidth : Int, val dataWidth : Int) extends IOBus[TLULHost]{
val io = IO(new Bundle{
val bus = new TLULHost(addrWidth, dataWidth)
val dataIO = EnqIO(UInt(dataWidth.W))
val xfer = Flipped(new XferDescBundle(addrWidth))
})
val sIdle :: sTransfer :: sWait :: Nil = Enum(3)
val state = RegInit(sIdle)
val xferCnt = RegInit(0.U(addrWidth.W))
val addr = RegInit(0.U(addrWidth.W))
val valid = RegInit(false.B)
val done = WireInit(false.B)
val xferValid = WireInit(false.B)
val xfer = WireInit(io.dataIO.ready && io.xfer.valid)
io.bus.d <> TLULD.tieOff(addrWidth, dataWidth)
// Producer to fifo
io.dataIO.bits := io.bus.d.data
io.dataIO.valid := xferValid
io.bus.a.valid := valid
io.bus.a.data := 0.U
io.bus.a.opcode := TLOp.Get
io.bus.a.param := 0.U
io.bus.a.size := 2.U
io.bus.a.source := 0.U
io.bus.a.address := addr
io.bus.a.corrupt := 0.U
io.bus.a.mask := 0xF.U
io.xfer.done := done
switch(state){
is(sIdle){
valid := false.B
io.bus.d.ready := false.B
done := false.B
xferValid := false.B
when(xfer) {
valid := true.B
state := sTransfer
xferCnt := io.xfer.length
addr := io.xfer.address
}
}
is(sTransfer){
io.bus.d.ready := true.B
xferValid := false.B
when(io.bus.a.ready) {
valid := false.B
state := sWait
when(xferCnt =/= 0.U) {
addr := addr + (dataWidth / 8).U
xferCnt := xferCnt - 1.U
}
// Don't stall if we receive same cycle d_valid
when(io.bus.d.valid) {
xferValid := true.B
when(xferCnt === 1.U) {
state := sIdle
done := true.B
}.otherwise {
valid := true.B
state := sTransfer
}
}
}
}
is(sWait){
valid := false.B
xferValid := false.B
io.bus.d.ready := true.B
when(io.bus.d.valid) {
xferValid := true.B
when(xferCnt === 0.U) {
state := sIdle
done := true.B
}.otherwise {
valid := true.B
state := sTransfer
}
}
}
}
}