package BACK import chisel3._ import chisel3.util._ class Header_Info_Bundle extends Bundle{ val length = UInt(8.W) // nlength * 16bits val operator = UInt(8.W) val param = Vec(3, UInt(16.W)) def init = operator === 0.U def sync = operator === 1.U def boardCast = operator === 2.U def uniCast = operator === 3.U } // class FSMC_Port_Bundle extends Bundle{ // val ADIn = Input(UInt(16.W)) // val ADOut = Output(UInt(16.W)) // val ADOEn = Output(Bool()) // val csn = Input(Bool()) // val rdn = Input(Bool()) // val wrn = Input(Bool()) // val advn = Input(Bool()) // } class ShinMstIO_Bundle extends Bundle{ val FSMC = new FSMC_Port_Bundle val interrupt = Output(Bool()) val testIO = Input(Bool()) val serOut = Output(Bool()) val serIn = Input(Bool()) val overCLK = Input(Bool()) } abstract class ShinMstPhyBase extends Module{ val io: ShinMstIO_Bundle = IO(new ShinMstIO_Bundle) val mirrorDown = Module(new MirrorSRAMDP()) val mirrorUp = Module(new MirrorSRAMDP()) val mirrorReg = Module(new MirrorSRAMDP()) val cdrOut = Module(new CDROut) val cdrIn = Module(new CDRIn ) io.serOut := cdrOut.io.serDat cdrIn.io.serDat := io.serIn cdrIn.io.overCLK := io.overCLK mirrorDown.io.clockA := clock.asBool mirrorDown.io.clockB := clock.asBool mirrorUp.io.clockA := clock.asBool mirrorUp.io.clockB := clock.asBool mirrorReg.io.addrB := DontCare mirrorReg.io.datawB := DontCare mirrorReg.io.enwB := false.B mirrorReg.io.enrB := false.B } trait ShinMstSend{ this: ShinMstPhyBase => val headByte = new Header_Info_Bundle.getWidth()/8 require( headByte == 8 ) val testIOShift = ShiftRegisters(io.testIO, headByte/2 + 1, false.B, true.B) val sendHeader = Reg( new Header_Info_Bundle ) when( ~testIOShift(0) & io.testIO ){ mirrorReg.io.addrB := 0.U mirrorReg.io.enrB := true.B } .elsewhen( ~testIOShift(1) & testIOShift(0) ){ mirrorReg.io.addrB := 1.U mirrorReg.io.enrB := true.B sendHeader := Cat( sendHeader.asUInt().tail(16), mirrorReg.io.datarB ).asTypeOf(new Header_Info_Bundle) } .elsewhen( ~testIOShift(2) & testIOShift(1) ){ mirrorReg.io.addrB := 2.U mirrorReg.io.enrB := true.B sendHeader := Cat( sendHeader.asUInt().tail(16), mirrorReg.io.datarB ).asTypeOf(new Header_Info_Bundle) } .elsewhen( ~testIOShift(3) & testIOShift(2) ){ mirrorReg.io.addrB := 3.U mirrorReg.io.enrB := true.B sendHeader := Cat( sendHeader.asUInt().tail(16), mirrorReg.io.datarB ).asTypeOf(new Header_Info_Bundle) } .elsewhen( ~testIOShift(4) & testIOShift(3) ){ sendHeader := Cat( sendHeader.asUInt().tail(16), mirrorReg.io.datarB ).asTypeOf(new Header_Info_Bundle) } val isSendTrig: Bool = ~testIOShift(4) & testIOShift(3) val isRecvEnd: Bool val isTimeout: Bool val sendStateNext = Wire( UInt(3.W) ) val sendStateCurr = RegNext( sendStateNext, 0.U ) val sendCntNext = Wire( UInt(10.W) ) val sendCntCurr = RegNext(sendCntNext) sendStateNext := Mux1H(Seq( (sendStateCurr === 0.U) -> Mux( isSendTrig, 1.U, 0.U ), (sendStateCurr === 1.U) -> Mux( cdrOut.io.axis.fire & sendCntCurr === ((headByte)-1).U, 2.U, 1.U ), (sendStateCurr === 2.U) -> Mux( cdrOut.io.axis.fire & sendCntCurr === (sendHeader.length << 1) - 1.U, 3.U, 2.U ), (sendStateCurr === 3.U) -> Mux( isRecvEnd | isTimeout, 0.U, 3.U ), )) sendCntNext := Mux1H(Seq( (sendStateCurr === 0.U) -> 0.U, (sendStateCurr === 1.U) -> Mux(cdrOut.io.axis.fire, Mux( sendStateNext =/= 2.U, sendCntCurr + 1.U, 0.U ), sendCntCurr), (sendStateCurr === 2.U) -> Mux(cdrOut.io.axis.fire, Mux( sendStateNext =/= 3.U, sendCntCurr + 1.U, 0.U ), sendCntCurr), )) cdrOut.io.axis.valid := sendStateCurr === 1.U | sendStateCurr === 2.U cdrOut.io.axis.bits.tdata := Mux1H(Seq( ( sendStateCurr === 1.U ) -> (sendHeader.asUInt >> (sendCntCurr << 3)), ( sendStateCurr === 2.U ) -> Mux( sendCntCurr.extract(0), mirrorDown.io.datarB(7,0), mirrorDown.io.datarB(15,8) ), )) cdrOut.io.axis.bits.tlast := sendStateCurr === 2.U & sendCntCurr === (sendHeader.length << 1) - 1.U cdrOut.io.axis.bits.tuser := false.B mirrorDown.io.enwB := false.B mirrorDown.io.datawB := 0.U mirrorDown.io.enrB := sendStateNext === 2.U mirrorDown.io.addrB := sendCntNext >> 1 } trait ShinMstRecv{ this: ShinMstPhyBase => def isSendTrig: Bool val recvStateNext = Wire( UInt(3.W) ) val recvStateCurr = RegNext( recvStateNext, 0.U ) val recvHeader = Reg( UInt( (new Header_Info_Bundle).getWidth.W) ) val recvCnt = Reg(UInt(10.W)) val recvLength = recvHeader.asTypeOf(new Header_Info_Bundle).length val isRecvEnd = recvStateCurr === 4.U io.interrupt := recvStateCurr === 4.U recvStateNext := Mux1H(Seq( (recvStateCurr === 0.U) -> Mux( isSendTrig, 1.U, 0.U ), //IDLE (recvStateCurr === 1.U) -> Mux( cdrIn.io.axis.fire, 2.U, 1.U ), //Arm (recvStateCurr === 2.U) -> Mux( cdrIn.io.axis.fire & recvCnt === ((recvHeader.getWidth()/8-1)*2).U, 3.U, 2.U ), //Header (recvStateCurr === 3.U) -> Mux( cdrIn.io.axis.fire & recvCnt === (recvHeader.length << 1), 4.U, 3.U ), //payload (recvStateCurr === 4.U) -> 0.U, //de-Arm )) when( recvStateCurr === 0.U | recvStateCurr === 1.U | recvStateCurr === 4.U ){ recvCnt := 0.U } .elsewhen( recvStateCurr === 2.U | recvStateCurr === 3.U ){ when( cdrIn.io.axis.fire ){ recvCnt := Mux( recvStateCurr === recvStateNext, recvCnt + 1.U, 0.U ) } } when( cdrIn.io.axis.fire & ( recvStateCurr === 1.U | recvStateCurr === 2.U )) { recvHeader := Cat( recvHeader.tail(8), cdrIn.io.axis.bits.tdata ) } val recvDataLatch = RegEnable( cdrIn.io.axis.bits.tdata, cdrIn.io.axis.fire & recvStateCurr === 3.U & recvCnt.extract(0) ) mirrorUp.io.enrB := false.B mirrorUp.io.enwB := cdrIn.io.axis.fire & recvStateCurr === 3.U & ~recvCnt.extract(0) mirrorUp.io.datawB := Cat( cdrIn.io.axis.bits.tdata, recvDataLatch ) mirrorUp.io.addrB := recvCnt >> 1 val recvRamAddr = Reg(UInt(8.W)) when( recvStateCurr === 2.U ){ recvRamAddr := 0.U } .elsewhen( recvStateCurr === 3.U & recvRamAddr =/= 4.U ){ recvRamAddr := recvRamAddr + 1.U } mirrorReg.io.addrB := recvRamAddr mirrorReg.io.datawB := Mux1H(Seq( (recvStateCurr === 3.U & recvRamAddr === 0.U) -> (recvHeader >> 16*3), (recvStateCurr === 3.U & recvRamAddr === 1.U) -> (recvHeader >> 16*2), (recvStateCurr === 3.U & recvRamAddr === 2.U) -> (recvHeader >> 16*1), (recvStateCurr === 3.U & recvRamAddr === 3.U) -> (recvHeader >> 16*0), )) mirrorReg.io.enwB := recvStateCurr === 3.U & recvRamAddr =/= 4.U val ( _, isTimeout ) = Counter( Range(0, 20000000), enable = recvStateCurr === 1.U | recvStateCurr === 2.U | recvStateCurr === 3.U, reset = recvStateCurr === 0.U | recvStateCurr === 4.U ) } abstract class ShinMstLinkBase extends ShinMstPhyBase with ShinMstSend with ShinMstRecv trait ShinMstInterface{ this: ShinMstLinkBase => io.FSMC.ADOEn := ~io.FSMC.rdn & ~io.FSMC.csn & io.FSMC.advn val latchAddr = RegEnable( io.FSMC.ADIn, ~io.FSMC.advn & ~io.FSMC.csn) val isAccessSRAM = ~latchAddr.extract(11) val isAccessReg = latchAddr.extract(11) val isAccessDown = ~latchAddr.extract(10) val activeAddr = latchAddr(9,0) mirrorDown.io.addrA := activeAddr mirrorDown.io.datawA := io.FSMC.ADIn mirrorDown.io.enwA := isAccessSRAM & ~io.FSMC.csn & ~io.FSMC.wrn & isAccessDown mirrorDown.io.enrA := isAccessSRAM & ~io.FSMC.csn & ~io.FSMC.rdn & isAccessDown mirrorUp.io.addrA := activeAddr mirrorUp.io.datawA := io.FSMC.ADIn mirrorUp.io.enwA := isAccessSRAM & ~io.FSMC.csn & ~io.FSMC.wrn & ~isAccessDown mirrorUp.io.enrA := isAccessSRAM & ~io.FSMC.csn & ~io.FSMC.rdn & ~isAccessDown mirrorReg.io.addrA := activeAddr mirrorReg.io.datawA := io.FSMC.ADIn mirrorReg.io.enwA := isAccessReg & ~io.FSMC.csn & ~io.FSMC.wrn mirrorReg.io.enrA := isAccessReg & ~io.FSMC.csn & ~io.FSMC.rdn io.FSMC.ADOut := Mux( isAccessReg, mirrorReg.io.datarA, Mux( isAccessDown, mirrorDown.io.datarA, mirrorUp.io.datarA) ) } class ShinMst extends ShinMstLinkBase with ShinMstInterface