Files
eb001/src/main/scala/mac/MacRx.scala
2023-09-25 14:18:27 +08:00

380 lines
13 KiB
Scala

package MAC
import chisel3._
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 with RequireAsyncReset{
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)
}