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 266bad0..0000000 Binary files a/.metals/metals.mv.db and /dev/null differ 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