package BACK import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ abstract class TLCDRBase(val edge: TLEdgeIn)(implicit p: Parameters) extends BackModule { class TLCDRIO extends Bundle{ val overCLK = Input(Bool()) val datIn = Input(Bool()) val datOut = Output(Bool()) val tla = Flipped(new DecoupledIO(new TLBundleA(edge.bundle))) val tld = new DecoupledIO(new TLBundleD(edge.bundle)) } val io: TLCDRIO = IO(new TLCDRIO) val CDRIn = Module(new CDRIn) CDRIn.io.serDat := io.datIn CDRIn.io.overCLK := io.overCLK val CDROut = Module(new CDROut) io.datOut := CDROut.io.serDat // CDRIn.io.axis = Decoupled(new AXIS_Bundle(8)) // CDROut.io.axis = Flipped(Decoupled(new AXIS_Bundle(8))) val txFifo = Module(new Queue(UInt(32.W), 8)) val rxFifo = Module(new Queue(UInt(32.W), 8)) } trait TLCDRTx{ this: TLCDRBase => val isTLReadTxStatus = io.tla.fire & io.tla.bits.address(6,0) === "h0".U & ( io.tla.bits.opcode === 4.U ) val isTLWriteTxLen = io.tla.fire & io.tla.bits.address(6,0) === "h4".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) val isTLWriteTxFifo = io.tla.fire & io.tla.bits.address(6,0) === "h8".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) val isTLWriteTxSoftReset = isTLWriteTxLen val txLen = RegInit(0.U(32.W)) val isTxBusy = RegInit(false.B) val isTxFull = ~txFifo.io.enq.ready val isTxError = RegInit(false.B) val intTxError = ~RegNext(isTxError, false.B) & isTxError val intTxFifoFull = ~RegNext(isTxFull, false.B) & isTxFull val intTxFinish = CDROut.io.axis.fire & CDROut.io.axis.bits.tlast val txCnt = Reg(UInt(2.W)) val txData = RegEnable( txFifo.io.deq.bits, txFifo.io.deq.fire) txFifo.io.deq.ready := Mux( isTxBusy, CDROut.io.axis.fire & txCnt === 3.U, true.B ) txFifo.reset := reset.asBool | isTLWriteTxLen CDROut.io.axis.bits.tdata := Mux1H(Seq( (txCnt === 0.U) -> txData( 7, 0), (txCnt === 1.U) -> txData(15, 8), (txCnt === 2.U) -> txData(23, 16), (txCnt === 3.U) -> txData(31, 24), )) CDROut.io.axis.bits.tlast := txLen === 0.U & ~txFifo.io.deq.valid & txCnt === 3.U CDROut.io.axis.bits.tuser := isTxError CDROut.io.axis.valid := isTxBusy when( isTLWriteTxLen ){ isTxBusy := false.B }.elsewhen( txFifo.io.deq.fire & ~isTxBusy ){ isTxBusy := true.B } .elsewhen( CDROut.io.axis.fire & CDROut.io.axis.bits.tlast ){ isTxBusy := false.B } when( isTLWriteTxLen ){ txCnt := 0.U } .elsewhen( CDROut.io.axis.fire ){ txCnt := txCnt + 1.U } when( isTLWriteTxLen ){ txLen := io.tla.bits.data } .elsewhen( CDROut.io.axis.fire ){ txLen := txLen - 1.U } txFifo.io.enq.bits := io.tla.bits.data txFifo.io.enq.valid := isTLWriteTxFifo & txLen =/= 0.U when( isTLReadTxStatus | isTLWriteTxLen ){ isTxError := false.B } .elsewhen( isTxFull & isTLWriteTxFifo ){ isTxError := true.B } .elsewhen( txLen === 0.U & isTLWriteTxFifo ){ isTxError := true.B } } trait TLCDRRx{ this: TLCDRBase => val isTLWriteRxSoftReset = io.tla.fire & io.tla.bits.address(6,0) === "h10".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) val isTLReadRxStatus = io.tla.fire & io.tla.bits.address(6,0) === "h14".U & ( io.tla.bits.opcode === 4.U ) val isTLReadRxLen = io.tla.fire & io.tla.bits.address(6,0) === "h18".U & ( io.tla.bits.opcode === 4.U ) val isTLReadRxFifo = io.tla.fire & io.tla.bits.address(6,0) === "h1c".U & ( io.tla.bits.opcode === 4.U ) val rxLen = RegInit(0.U(32.W)) // val isRxBusy = RegInit(false.B) val isRxValid = rxFifo.io.enq.fire val isRxError = RegInit(false.B) val intRxError = ~RegNext(isRxError, false.B) & isRxError val intRxValid = ~RegNext(isRxValid, false.B) & isRxValid val rxCnt = RegInit(0.U(2.W)) val rxData = Reg(UInt(24.W)) when( isTLWriteRxSoftReset ){ rxCnt := 0.U } .elsewhen( CDRIn.io.axis.fire ){ rxCnt := rxCnt + 1.U rxData := Mux1H(Seq( (rxCnt === 0.U) -> Cat( 0.U(24.W), CDRIn.io.axis.bits.tdata ), (rxCnt === 1.U) -> Cat( 0.U(16.W), CDRIn.io.axis.bits.tdata, rxData( 7,0) ), (rxCnt === 2.U) -> Cat( 0.U(8.W ), CDRIn.io.axis.bits.tdata, rxData(15,0) ), // (rxCnt === 3.U) -> Cat( CDRIn.io.axis.bits.tdata, rxData(23,0) ), )) } when( isTLWriteRxSoftReset ){ rxLen := 0.U } .elsewhen( CDRIn.io.axis.fire ){ rxLen := rxLen + 1.U } rxFifo.io.enq.valid := CDRIn.io.axis.fire & ( rxCnt === 3.U | CDRIn.io.axis.bits.tlast ) rxFifo.io.enq.bits := Mux1H(Seq( (rxCnt === 0.U) -> Cat( 0.U(24.W), CDRIn.io.axis.bits.tdata ), (rxCnt === 1.U) -> Cat( 0.U(16.W), CDRIn.io.axis.bits.tdata, rxData( 7,0) ), (rxCnt === 2.U) -> Cat( 0.U(8.W ), CDRIn.io.axis.bits.tdata, rxData(15,0) ), (rxCnt === 3.U) -> Cat( CDRIn.io.axis.bits.tdata, rxData(23,0) ), )) CDRIn.io.axis.ready := true.B rxFifo.reset := reset.asBool | isTLWriteRxSoftReset rxFifo.io.deq.ready := isTLReadRxFifo when( isTLWriteRxSoftReset ){ isRxError := false.B } .elsewhen( rxFifo.io.enq.valid & ~rxFifo.io.enq.ready ){ isRxError := true.B printf("Warning, RxFifo Overflow!\n") } } class TLCDR(edge: TLEdgeIn)(implicit p: Parameters) extends TLCDRBase(edge) with TLCDRTx with TLCDRRx{ val tlaInfo = Reg(new TLBundleA(edge.bundle)) val rdata = Reg(UInt(32.W)) val tlAReady = RegInit(true.B) val tlDValid = RegInit(false.B) val isRead = Reg(Bool()) io.tla.ready := tlAReady io.tld.valid := tlDValid when( io.tla.fire ) { tlaInfo := io.tla.bits when( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) { isRead := false.B } .elsewhen( io.tla.bits.opcode === 4.U ) { isRead := true.B } .otherwise{ assert( false.B, "Assert Failed! Unsupport Operation!" ) } } when( io.tla.fire ){ tlAReady := false.B tlDValid := true.B } .elsewhen( io.tld.fire ) { tlAReady := true.B tlDValid := false.B } when(isRead) { io.tld.bits := edge.AccessAck(tlaInfo, rdata) } .otherwise { io.tld.bits := edge.AccessAck(tlaInfo) } when( isTLReadTxStatus){ rdata := Cat( isTxBusy, isTxFull, isTxError ) } .elsewhen(isTLWriteTxLen ){ rdata := 0.U } .elsewhen(isTLWriteTxFifo ){ rdata := 0.U } .elsewhen(isTLWriteTxSoftReset){ rdata := 0.U } .elsewhen(isTLWriteRxSoftReset){ rdata := 0.U } .elsewhen(isTLReadRxStatus ){ rdata := Cat( isRxValid, isRxError ) } .elsewhen(isTLReadRxLen ){ rdata := rxLen } .elsewhen(isTLReadRxFifo ){ rdata := rxFifo.io.deq.bits } }