From 505aa7326a6229422e01611056a767610c16705b Mon Sep 17 00:00:00 2001 From: RuigeLee Date: Wed, 21 Jun 2023 21:55:16 +0800 Subject: [PATCH] finish macrx --- .gitignore | 2 + .metals/metals.lock.db | 6 - .metals/metals.mv.db | Bin 331776 -> 0 bytes src/main/scala/mac/MacRx.scala | 375 ++++++++++++++++++++++++++++++++- src/test/scala/gcd/test.scala | 2 +- 5 files changed, 377 insertions(+), 8 deletions(-) delete mode 100644 .metals/metals.lock.db delete mode 100644 .metals/metals.mv.db diff --git a/.gitignore b/.gitignore index 12033d3..ede2990 100644 --- a/.gitignore +++ b/.gitignore @@ -339,3 +339,5 @@ project/plugins/project/ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +.metals/ +generated/ diff --git a/.metals/metals.lock.db b/.metals/metals.lock.db deleted file mode 100644 index 7622a3c..0000000 --- a/.metals/metals.lock.db +++ /dev/null @@ -1,6 +0,0 @@ -#FileLock -#Tue Jun 20 09:28:51 IRKT 2023 -hostName=localhost -id=188d66b3b3748481f5b9d61add429f6624c89a575b9 -method=file -server=localhost\:58608 diff --git a/.metals/metals.mv.db b/.metals/metals.mv.db deleted file mode 100644 index 266bad0d35a2b55e7be1e31026d23be4c41b73d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331776 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 diff --git a/src/main/scala/mac/MacRx.scala b/src/main/scala/mac/MacRx.scala index 869c69c..67f1dc6 100644 --- a/src/main/scala/mac/MacRx.scala +++ b/src/main/scala/mac/MacRx.scala @@ -1,6 +1,379 @@ package MAC import chisel3._ -import chisel3.util +import chisel3.util._ + +class MacRxIO extends Bundle{ + + val MRxDV = Input(Bool()) + val MRxD = Input(UInt(4.W)) + val Transmitting = Input(Bool()) + val HugEn = Input(Bool()) + val DlyCrcEn = Input(Bool()) + val MaxFL = Input(UInt(16.W)) + val r_IFG = Input(Bool()) + val MAC = Input(UInt(48.W)) // Station Address + val r_Bro = Input(Bool()) // broadcast disable + val r_Pro = Input(Bool()) // promiscuous enable + val r_HASH0 = Input(UInt(32.W)) // lower 4 bytes Hash Table + val r_HASH1 = Input(UInt(32.W)) // upper 4 bytes Hash Table + val PassAll = Input(Bool()) + val ControlFrmAddressOK = Input(Bool()) + + val RxData = Output(UInt(8.W)) + val RxValid = Output(Bool()) + val RxStartFrm = Output(Bool()) + val RxEndFrm = Output(Bool()) + val ByteCnt = Output(UInt(16.W)) + val ByteCntEq0 = Output(Bool()) + val ByteCntGreat2 = Output(Bool()) + val ByteCntMaxFrame = Output(Bool()) + val CrcError = Output(Bool()) + val StateIdle = Output(Bool()) + val StatePreamble = Output(Bool()) + val StateSFD = Output(Bool()) + val StateData = Output(UInt(2.W)) + val RxAbort = Output(Bool()) + val AddressMiss = Output(Bool()) +} + + +abstract class MacRxBase extends Module{ + val io: MacRxIO = IO(new MacRxIO) + + val MRxDEqD = io.MRxD === "hd".U + val MRxDEq5 = io.MRxD === "h5".U + + val IFGCounterEq24 = Wire(Bool()) + + val ByteCntEq0 = Wire(Bool()) + io.ByteCntEq0 := ByteCntEq0 + + val ByteCntEq1 = Wire(Bool()) + val ByteCntEq2 = Wire(Bool()) + val ByteCntEq3 = Wire(Bool()) + val ByteCntEq4 = Wire(Bool()) + val ByteCntEq5 = Wire(Bool()) + val ByteCntEq6 = Wire(Bool()) + val ByteCntEq7 = Wire(Bool()) + + val ByteCntSmall7 = Wire(Bool()) + + val DlyCrcCnt = RegInit(0.U(4.W)) + + val StateData0 = RegInit(false.B) + val StateData1 = RegInit(false.B) + val StateIdle = RegInit(false.B); io.StateIdle := StateIdle + val StateDrop = RegInit(true.B) + val StatePreamble = RegInit(false.B); io.StatePreamble := StatePreamble + val StateSFD = RegInit(false.B); io.StateSFD := StateSFD + + val RxData_d = RegInit(0.U(8.W)) + val RxData = RegNext(RxData_d, 0.U); io.RxData := RxData + + val Broadcast = RegInit(false.B) + val Multicast = RegInit(false.B) + + val Crc = RegInit("hFFFFFFFF".U(32.W)) + + + +} + +trait MacRxFSM { this: MacRxBase => + + val StateData = Cat( StateData1, StateData0 ) + io.StateData := StateData + + // Defining the next state + val StartIdle = ~io.MRxDV & (StateDrop | StatePreamble | StateSFD | StateData0 | StateData1 ) + val StartPreamble = io.MRxDV & ~MRxDEq5 & (StateIdle & ~io.Transmitting) + val StartSFD = io.MRxDV & MRxDEq5 & (StateIdle & ~io.Transmitting | StatePreamble) + val StartData0 = io.MRxDV & (StateSFD & MRxDEqD & IFGCounterEq24 | StateData1) + val StartData1 = io.MRxDV & StateData0 & (~io.ByteCntMaxFrame) + val StartDrop = io.MRxDV & ( + (StateIdle & io.Transmitting) | (StateSFD & ~IFGCounterEq24 & MRxDEqD ) | ( StateData0 & io.ByteCntMaxFrame) + ) + + + when(StartPreamble | StartSFD | StartDrop){ + StateIdle := false.B + } .elsewhen( StartIdle ){ + StateIdle := true.B + } + + when( StartIdle ){ + StateDrop := false.B + } .elsewhen(StartDrop){ + StateDrop := true.B + } + + when(StartSFD | StartIdle | StartDrop ){ + StatePreamble := false.B + } .elsewhen(StartPreamble){ + StatePreamble := true.B + } + + when(StartPreamble | StartIdle | StartData0 | StartDrop){ + StateSFD := false.B + } .elsewhen (StartSFD){ + StateSFD := true.B + } + + + when(StartIdle | StartData1 | StartDrop){ + StateData0 := false.B + } .elsewhen(StartData0){ + StateData0 := true.B + } + + + when(StartIdle | StartData0 | StartDrop){ + StateData1 := false.B + } .elsewhen(StartData1){ + StateData1 := true.B + } + +} + +trait MacRxCounter { this: MacRxBase => + + val ByteCnt = RegInit(0.U(16.W)) + val IFGCounter = RegInit(0.U(5.W)) + + val ByteCntMax = ByteCnt === "hffff".U + + val ResetByteCounter = io.MRxDV & (io.StateSFD & MRxDEqD | io.StateData.extract(0) & io.ByteCntMaxFrame) + + val IncrementByteCounter = + ~ResetByteCounter & io.MRxDV & ( + io.StatePreamble | io.StateSFD | io.StateIdle & ~io.Transmitting | + (io.StateData.extract(1) & ~ByteCntMax & ~(io.DlyCrcEn & DlyCrcCnt.orR)) + ) + + val ByteCntDelayed = ByteCnt + 4.U + io.ByteCnt := Mux(io.DlyCrcEn, ByteCntDelayed, ByteCnt) + + when( DlyCrcCnt === 9.U ){ + DlyCrcCnt := 0.U + } .elsewhen(io.DlyCrcEn & io.StateSFD){ + DlyCrcCnt := 1.U + } .elsewhen(io.DlyCrcEn & (DlyCrcCnt.orR)){ + DlyCrcCnt := DlyCrcCnt + 1.U + } + + when( ResetByteCounter ){ + ByteCnt := 0.U + } .elsewhen(IncrementByteCounter){ + ByteCnt := ByteCnt + 1.U + } + + ByteCntEq0 := ByteCnt === 0.U + ByteCntEq1 := ByteCnt === 1.U + ByteCntEq2 := ByteCnt === 2.U + ByteCntEq3 := ByteCnt === 3.U + ByteCntEq4 := ByteCnt === 4.U + ByteCntEq5 := ByteCnt === 5.U + ByteCntEq6 := ByteCnt === 6.U + ByteCntEq7 := ByteCnt === 7.U + + io.ByteCntGreat2 := ByteCnt > 2.U + ByteCntSmall7 := ByteCnt < 7.U + + io.ByteCntMaxFrame := (ByteCnt === io.MaxFL) & ~io.HugEn; + + + val ResetIFGCounter = io.StateSFD & io.MRxDV & MRxDEqD | StateDrop; + val IncrementIFGCounter = ~ResetIFGCounter & (StateDrop | io.StateIdle | io.StatePreamble | io.StateSFD) & ~IFGCounterEq24; + + when( ResetIFGCounter ){ + IFGCounter := 0.U + } .elsewhen(IncrementIFGCounter){ + IFGCounter := IFGCounter + 1.U + } + + IFGCounterEq24 := (IFGCounter === "h18".U) | io.r_IFG; // 24*400 = 9600 ns or r_IFG is set to 1 + +} + +trait MacRxFAddrCheck { this: MacRxBase => + + val HashBit = Wire(UInt(1.W)) + + + val BroadcastOK = Broadcast & ~io.r_Bro + val RxCheckEn = io.StateData.orR + + val RxAbort = RegInit(false.B) // Address Error Reported at end of address cycle// RxAbort clears after one cycle + val AddressMiss = RegInit(false.B) // This ff holds the "Address Miss" information that is written to the RX BD status. + val MulticastOK = RegInit(false.B) // Hash Address Check, Multicast + val UnicastOK = RegInit(false.B) // Address Detection (unicast) // start with ByteCntEq2 due to delay of addres from RxData + + io.RxAbort := RxAbort + io.AddressMiss := AddressMiss + + + val RxAddressInvalid = ~(UnicastOK | BroadcastOK | MulticastOK | io.r_Pro); + + val CrcHash = RegInit(0.U(6.W)) + val CrcHashGood = RegNext(StateData0 & ByteCntEq6) // Latching CRC for use in the hash table + + when(RxAddressInvalid & ByteCntEq7 & RxCheckEn){ + RxAbort := true.B + } .otherwise{ + RxAbort := false.B + } + + when(ByteCntEq0){ + AddressMiss := false.B + } .elsewhen(ByteCntEq7 & RxCheckEn){ + AddressMiss := (~(UnicastOK | BroadcastOK | MulticastOK | (io.PassAll & io.ControlFrmAddressOK))); + } + + when(io.RxEndFrm | RxAbort){ + MulticastOK := false.B + } .elsewhen(CrcHashGood & Multicast){ + MulticastOK := HashBit + } + + when(RxCheckEn & ByteCntEq2){ + UnicastOK := RxData === io.MAC(47,40) + } .elsewhen(RxCheckEn & ByteCntEq3){ + UnicastOK := ( RxData === io.MAC(39,32)) & UnicastOK + } .elsewhen(RxCheckEn & ByteCntEq4){ + UnicastOK := ( RxData === io.MAC(31,24)) & UnicastOK + } .elsewhen(RxCheckEn & ByteCntEq5){ + UnicastOK := ( RxData === io.MAC(23,16)) & UnicastOK + } .elsewhen(RxCheckEn & ByteCntEq6){ + UnicastOK := ( RxData === io.MAC(15,8)) & UnicastOK + } .elsewhen(RxCheckEn & ByteCntEq7){ + UnicastOK := ( RxData === io.MAC(7,0)) & UnicastOK + } .elsewhen(io.RxEndFrm | RxAbort){ + UnicastOK := false.B + } + + + val IntHash = Mux(CrcHash.extract(5), io.r_HASH1, io.r_HASH0) + val ByteHash = + Mux1H(Seq( + (CrcHash(4,3) === "b00".U) -> IntHash(7 ,0), + (CrcHash(4,3) === "b01".U) -> IntHash(15,8), + (CrcHash(4,3) === "b10".U) -> IntHash(23,16), + (CrcHash(4,3) === "b11".U) -> IntHash(31,24), + )) + + HashBit := ByteHash >> CrcHash(2,0) + + when(StateIdle){ + CrcHash := 0.U + } .elsewhen(StateData0 & ByteCntEq6){ + CrcHash := Crc(31,26) + } + +} + +trait MacRxCRC { this: MacRxBase => + + val Data_Crc = Cat(io.MRxD.extract(0),io.MRxD.extract(1),io.MRxD.extract(2),io.MRxD.extract(3)) + val Enable_Crc = io.MRxDV & (io.StateData.orR & ~io.ByteCntMaxFrame) + val Initialize_Crc = io.StateSFD | (io.DlyCrcEn & DlyCrcCnt > 0.U & DlyCrcCnt < 9.U) + + when( Initialize_Crc ){ + Crc := "hFFFFFFFF".U + } .otherwise{ + Crc := Cat( + Crc.extract(27), + Crc.extract(26), + (Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(25), + (Enable_Crc & (Data_Crc.extract(2) ^ Crc.extract(30))) ^ Crc.extract(24), + (Enable_Crc & (Data_Crc.extract(1) ^ Crc.extract(29))) ^ Crc.extract(23), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(0) ^ Crc.extract(31) ^ Crc.extract(28))) ^ Crc.extract(22), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Crc.extract(31) ^ Crc.extract(30))) ^ Crc.extract(21), + (Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(30) ^ Crc.extract(29))) ^ Crc.extract(20), + (Enable_Crc & (Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(29) ^ Crc.extract(28))) ^ Crc.extract(19), + (Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))) ^ Crc.extract(18), + Crc.extract(17), + Crc.extract(16), + (Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(15), + (Enable_Crc & (Data_Crc.extract(2) ^ Crc.extract(30))) ^ Crc.extract(14), + (Enable_Crc & (Data_Crc.extract(1) ^ Crc.extract(29))) ^ Crc.extract(13), + (Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))) ^ Crc.extract(12), + (Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(11), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(10), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(9), + (Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract(8), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(7), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(6), + (Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract(5), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(4), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(3), + (Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract( 2), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(1), + (Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(0), + Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30) ^ Crc.extract(31)), + Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(30)), + Enable_Crc & (Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29)), + Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28)) + ) + } + + io.CrcError := Crc =/= "hc704dd7b".U // CRC not equal to magic number + + +} + +class MacRx extends MacRxBase with MacRxFSM with MacRxCounter with MacRxFAddrCheck with MacRxCRC{ + + + + val GenerateRxValid = StateData0 & (~ByteCntEq0 | DlyCrcCnt >= 3.U); + val DelayData = RegNext(StateData0, false.B) + val LatchedByte = RegInit(0.U(8.W)) + when(true.B) { + LatchedByte := Cat(io.MRxD, LatchedByte(7,4))// Latched byte + } + + + + // Output byte stream + when( GenerateRxValid ){ + RxData_d := LatchedByte & Fill(8, StateData0 | StateData1) // Data goes through only in data state + } .elsewhen(~DelayData){ + RxData_d := 0.U // Delaying data to be valid for two cycles. // Zero when not active. + } + + + when(StateData0 & LatchedByte =/= "hFF".U & ByteCntSmall7){ + Broadcast := false.B + } .elsewhen(StateData0 & LatchedByte === "hFF".U & ByteCntEq1){ + Broadcast := true.B + } .elsewhen(io.RxAbort | io.RxEndFrm){ + Broadcast := false.B + } + + + when(StateData0 & ByteCntEq1 & LatchedByte.extract(0)){ + Multicast := true.B + } .elsewhen(io.RxAbort | io.RxEndFrm){ + Multicast := false.B + } + + + + io.RxValid := ShiftRegister(GenerateRxValid, 2, false.B, true.B) + + + val GenerateRxStartFrm = StateData0 & ( (ByteCntEq1 & ~io.DlyCrcEn) | ((DlyCrcCnt === 3.U) & io.DlyCrcEn) ) + + io.RxStartFrm := ShiftRegister(GenerateRxStartFrm, 2, false.B, true.B) + + + val GenerateRxEndFrm = StateData0 & ((~io.MRxDV & io.ByteCntGreat2) | io.ByteCntMaxFrame) + val DribbleRxEndFrm = StateData1 & ~io.MRxDV & io.ByteCntGreat2 + + val RxEndFrm_d = RegNext(GenerateRxEndFrm, false.B) + io.RxEndFrm := RegNext(RxEndFrm_d | DribbleRxEndFrm, false.B) + +} diff --git a/src/test/scala/gcd/test.scala b/src/test/scala/gcd/test.scala index 4740877..66e8e26 100644 --- a/src/test/scala/gcd/test.scala +++ b/src/test/scala/gcd/test.scala @@ -7,7 +7,7 @@ import chisel3.stage._ object testModule extends App { (new chisel3.stage.ChiselStage).execute( Array("--target-dir", "generated/", "-e", "verilog" ) ++ args, Seq( ChiselGeneratorAnnotation(() => { - new MIIM() + new MacRx() }) )) } \ No newline at end of file