blob: 5485557adab6055cf73aed107f8f2cb97702c0fc [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 TLULWriter(val addrWidth : Int, val dataWidth : Int) extends IOBus[TLULHost]{
val io = IO(new Bundle{
val bus = new TLULHost(addrWidth, dataWidth)
val dataIO = DeqIO(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 addrValid = RegInit(false.B)
val valid = RegInit(false.B)
val done = WireInit(false.B)
val xferValid = WireInit(false.B)
io.bus.d <> TLULD.tieOff(addrWidth, dataWidth)
// Consumer of fifo
io.dataIO.ready := xferValid
io.bus.a.valid := valid
io.bus.a.data := io.dataIO.bits
// Note: Write port does not support TLUL partial put op
io.bus.a.opcode := TLOp.PutFull
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
// Sync valid signals from the data queue and
// address generator here.
when(io.xfer.valid) {
addrValid := true.B
}
when(io.dataIO.valid && addrValid) {
valid := true.B
state := sTransfer
xferCnt := io.xfer.length
addr := io.xfer.address
addrValid := false.B
}
}
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
}
}
}
}
}