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 dDatIn = Input(Bool()) val dDatOut = Output(Bool()) val uDatIn = Input(Bool()) val uDatOut = Output(Bool()) val tla = Flipped(new DecoupledIO(new TLBundleA(edge.bundle))) val tld = new DecoupledIO(new TLBundleD(edge.bundle)) val interrupt = Output(Vec(4, Bool())) } val io: TLCDRIO = IO(new TLCDRIO) val dirSel = RegInit(false.B) val CDRIn = Module(new CDRIn) CDRIn.io.serDat := Mux( ~dirSel, io.dDatIn, io.uDatIn ) CDRIn.io.overCLK := io.overCLK val CDROut = Module(new CDROut) io.dDatOut := ~dirSel & CDROut.io.serDat io.uDatOut := dirSel & 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(31, 24), (txCnt === 1.U) -> txData(23, 16), (txCnt === 2.U) -> txData(15, 8), (txCnt === 3.U) -> txData( 7, 0), )) CDROut.io.axis.bits.tlast := ~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 isAxisEnd = RegInit(false.B) val isRxEnd = isAxisEnd & ~rxFifo.io.deq.valid val intRxError = ~RegNext(isRxError, false.B) & isRxError // val intRxValid = ~RegNext(isRxValid, false.B) & isRxValid val intRxStart = rxLen === 0.U & CDRIn.io.axis.fire val intRxEnd = ~RegNext(isRxEnd, false.B) & isRxEnd val rxCnt = RegInit(0.U(2.W)) val rxData = Reg(UInt(32.W)) when(isTLWriteRxSoftReset ){ isAxisEnd := false.B } .elsewhen( CDRIn.io.axis.fire & CDRIn.io.axis.bits.tlast ){ isAxisEnd := true.B } when( isTLWriteRxSoftReset ){ rxCnt := 0.U } .elsewhen( CDRIn.io.axis.fire ){ rxCnt := rxCnt + 1.U rxData := Mux1H(Seq( (rxCnt === 0.U) -> Cat( CDRIn.io.axis.bits.tdata, 0.U(24.W) ), (rxCnt === 1.U) -> Cat( rxData(31,24), CDRIn.io.axis.bits.tdata, 0.U(16.W) ), (rxCnt === 2.U) -> Cat( rxData(31,16), CDRIn.io.axis.bits.tdata, 0.U(8.W ) ), // (rxCnt === 3.U) -> Cat( rxData(31,8) , CDRIn.io.axis.bits.tdata ), )) } 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( CDRIn.io.axis.bits.tdata, 0.U(24.W) ), (rxCnt === 1.U) -> Cat( rxData(31,24), CDRIn.io.axis.bits.tdata, 0.U(16.W) ), (rxCnt === 2.U) -> Cat( rxData(31,16), CDRIn.io.axis.bits.tdata, 0.U(8.W ) ), (rxCnt === 3.U) -> Cat( rxData(31,8) , CDRIn.io.axis.bits.tdata ), )) 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 isWriteTransDir = io.tla.fire & io.tla.bits.address(6,0) === "hc".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) 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()) when( isWriteTransDir ){ dirSel := io.tla.bits.data } io.tla.ready := tlAReady & txFifo.io.enq.ready & ( Mux(io.tla.bits.address(6,0) === "h1c".U & ( io.tla.bits.opcode === 4.U ), rxFifo.io.deq.valid, true.B) ) io.tld.valid := tlDValid io.interrupt(0) := intTxError io.interrupt(1) := intRxError io.interrupt(2) := intRxStart io.interrupt(3) := intRxEnd 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 } }