Files
eb001/src/main/scala/Switch/mac/MacTx.scala
RuigeLee 1e6f2df9ae clean up
2023-10-25 16:04:53 +08:00

403 lines
14 KiB
Scala

package MAC
import chisel3._
import chisel3.util._
class MacTxIO extends Bundle{
val TxStartFrm = Input(Bool()) // Transmit packet start frame
val TxEndFrm = Input(Bool()) // Transmit packet end frame
val TxData = Input(UInt(8.W)) // Transmit packet data byte
val CarrierSense = Input(Bool()) // Carrier sense (synchronized)
val Collision = Input(Bool()) // Collision (synchronized)
val Pad = Input(Bool()) // Pad enable (from register)
val CrcEn = Input(Bool()) // Crc enable (from register)
val FullD = Input(Bool()) // Full duplex (from register)
val DlyCrcEn = Input(Bool()) // Delayed Crc enabled (from register)
val MinFL = Input(UInt(16.W)) // Minimum frame length (from register)
val MaxFL = Input(UInt(16.W)) // Maximum frame length (from register)
val IPGT = Input(UInt(7.W)) // Back to back transmit inter packet gap parameter (from register)
val IPGR1 = Input(UInt(7.W)) // Non back to back transmit inter packet gap parameter IPGR1 (from register)
val IPGR2 = Input(UInt(7.W)) // Non back to back transmit inter packet gap parameter IPGR2 (from register)
val CollValid = Input(UInt(6.W)) // Valid collision window (from register)
val ExDfrEn = Input(Bool()) // Excessive defferal enable (from register)
val MTxD = Output(UInt(4.W)) // Transmit nibble (to PHY)
val MTxEn = Output(Bool()) // Transmit enable (to PHY)
val MTxErr = Output(Bool()) // Transmit error (to PHY)
val TxDone = Output(Bool()) // Transmit packet done (to RISC)
val TxAbort = Output(Bool()) // Transmit packet abort (to RISC)
val TxUsedData = Output(Bool()) // Transmit packet used data (to RISC)
val WillTransmit = Output(Bool()) // Will transmit (to RxEthMAC)
val ResetCollision = Output(Bool()) // Reset Collision (for synchronizing collision)
val StartTxDone = Output(Bool())
val StartTxAbort = Output(Bool())
val MaxCollisionOccured= Output(Bool())
val LateCollision = Output(Bool())
val DeferIndication = Output(Bool())
val StatePreamble = Output(Bool())
val StateData = Output(UInt(2.W))
}
abstract class MacTxBase extends Module with RequireAsyncReset{
val io: MacTxIO = IO(new MacTxIO)
val StartIPG = Wire(Bool())
val StartPreamble = Wire(Bool())
val StartData = Wire( Vec(2,Bool()))
val StartFCS = Wire(Bool())
val StartJam = Wire(Bool())
val StartDefer = Wire(Bool())
val StateSFD = Wire(Bool())
val CrcError = Wire(Bool())
val NibbleMinFl = Wire(Bool())
val ExcessiveDefer = Wire(Bool())
val StateIPG = RegInit(false.B)
val StateIdle = RegInit(false.B)
val StatePreamble = RegInit(false.B); io.StatePreamble := StatePreamble
val StateData = RegNext( Cat(StartData(1), StartData(0)), 0.U(2.W)); io.StateData := StateData
val StatePAD = RegInit(false.B)
val StateFCS = RegInit(false.B)
val StateJam = RegInit(false.B)
val StateJam_q = RegNext(StateJam, false.B)
val StateDefer = RegInit(true.B)
val Rule1 = RegInit(false.B)
val ColWindow = RegInit(true.B)
val DlyCrcCnt = RegInit(0.U(3.W)) // Delayed CRC counter
val PacketFinished_q = RegInit(false.B)
val ByteCnt = RegInit(0.U(16.W)) // Transmit Byte Counter
val NibCnt = RegInit(0.U(16.W)) // Nibble Counter
val NibCntEq7 = NibCnt === 7.U
val NibCntEq15 = NibCnt === 15.U
}
trait MacTxFSM { this: MacTxBase =>
// Defining the next state
StartIPG := StateDefer & ~ExcessiveDefer & ~io.CarrierSense
val StartIdle = StateIPG & (Rule1 & NibCnt(6,0) >= io.IPGT | ~Rule1 & NibCnt(6,0) >= io.IPGR2)
StartPreamble := StateIdle & io.TxStartFrm & ~io.CarrierSense
StartData(0) := ~io.Collision & (StatePreamble & NibCntEq15 | StateData(1) & ~io.TxEndFrm)
StartData(1) := ~io.Collision & StateData(0)
val StartPAD = ~io.Collision & StateData(1) & io.TxEndFrm & io.Pad & ~NibbleMinFl
StartFCS :=
(~io.Collision & StateData(1) & io.TxEndFrm & (~io.Pad | io.Pad & NibbleMinFl) & io.CrcEn) |
(~io.Collision & StatePAD & NibbleMinFl & io.CrcEn)
StartJam := (io.Collision ) & ((StatePreamble & NibCntEq15) | (StateData(1) | StateData(0)) | StatePAD | StateFCS)
StartDefer :=
(StateIPG & ~Rule1 & io.CarrierSense & NibCnt(6,0) <= io.IPGR1 & NibCnt(6,0) =/= io.IPGR2) |
(StateIdle & io.CarrierSense) |
(StateJam & NibCntEq7) |
io.StartTxDone
io.DeferIndication := StateIdle & io.CarrierSense
when(StartDefer | StartIdle){
StateIPG := false.B
}.elsewhen(StartIPG){
StateIPG := true.B
}
when(StartDefer | StartPreamble){
StateIdle := false.B
}.elsewhen(StartIdle){
StateIdle := true.B
}
when(StartData(0) | StartJam){
StatePreamble := false.B
} .elsewhen(StartPreamble){
StatePreamble := true.B
}
when(StartFCS | StartJam){
StatePAD := false.B
}.elsewhen(StartPAD){
StatePAD := true.B
}
when(StartJam | StartDefer){
StateFCS := false.B
} .elsewhen(StartFCS){
StateFCS := true.B
}
when(StartDefer){
StateJam := false.B
} .elsewhen(StartJam){
StateJam := true.B
}
when(StartIPG){
StateDefer := false.B
} .elsewhen(StartDefer){
StateDefer := true.B
}
// This sections defines which interpack gap rule to use
when(StateIdle){
Rule1 := false.B
} .elsewhen(StatePreamble | io.FullD){
Rule1 := true.B
}
}
trait MacTxCounter { this: MacTxBase =>
val ByteCntMax = Wire(Bool())
val IncrementNibCnt =
StateIPG | StatePreamble |
(StateData(1) | StateData(0)) |
StatePAD | StateFCS | StateJam |
(StateDefer & ~ExcessiveDefer & io.TxStartFrm)
val ResetNibCnt =
(StateDefer & ExcessiveDefer & ~io.TxStartFrm) |
(StatePreamble & NibCntEq15) |
(StateJam & NibCntEq7) |
StateIdle | StartDefer | StartIPG | StartFCS | StartJam
when(ResetNibCnt){
NibCnt := 0.U
} .elsewhen(IncrementNibCnt){
NibCnt := NibCnt + 1.U
}
NibbleMinFl := NibCnt >= (((io.MinFL-4.U)<<1) - 1.U) // FCS should not be included in NibbleMinFl
ExcessiveDefer := NibCnt(13,0) === "h17b7".U & ~io.ExDfrEn; // 6071 nibbles
val IncrementByteCnt =
(StateData(1) & ~ByteCntMax) |
((StatePAD | StateFCS) & NibCnt.extract(0) & ~ByteCntMax)
val ResetByteCnt =
(StateIdle & io.TxStartFrm) |
PacketFinished_q
ByteCntMax := ByteCnt.andR
when(ResetByteCnt){
ByteCnt := 0.U
} .elsewhen(IncrementByteCnt){
ByteCnt := ByteCnt + 1.U
}
when((StateData(1) & DlyCrcCnt === 4.U) | StartJam | PacketFinished_q){
DlyCrcCnt := 0.U
}.elsewhen(io.DlyCrcEn & (StateSFD | StateData(1) & (DlyCrcCnt.orR))){
DlyCrcCnt := DlyCrcCnt + 1.U
}
}
trait MacTxCRC{ this: MacTxBase =>
val Initialize_Crc = StateIdle | StatePreamble | (DlyCrcCnt.orR)
val Enable_Crc = ~StateFCS
val Data_Crc =
Mux1H(Seq(
StateData(0) -> Cat( io.TxData(0), io.TxData(1), io.TxData(2), io.TxData(3) ),
StateData(1) -> Cat( io.TxData(4), io.TxData(5), io.TxData(6), io.TxData(7) ),
))
val Crc = RegInit("hFFFFFFFF".U(32.W))
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))
)
}
CrcError := Crc =/= "hc704dd7b".U // CRC not equal to magic number
}
class MacTx extends MacTxBase with MacTxFSM with MacTxCounter with MacTxCRC {
val MTxD = RegInit(0.U(4.W)); io.MTxD := MTxD
val StopExcessiveDeferOccured = RegInit(false.B)
val StatusLatch = RegInit(false.B)
val TxUsedData = RegNext(StartData(0) | StartData(1), false.B); io.TxUsedData := TxUsedData
val TxDone = RegInit(false.B); io.TxDone := TxDone
val TxAbort = RegInit(false.B); io.TxAbort := TxAbort
val MTxEn = RegNext(StatePreamble | (StateData(0) | StateData(1)) | StatePAD | StateFCS | StateJam, false.B); io.MTxEn := MTxEn
io.MTxErr := false.B
val WillTransmit = RegNext(StartPreamble | StatePreamble | (StateData(0) | StateData(1)) | StatePAD | StateFCS | StateJam, false.B); io.WillTransmit := WillTransmit// WillTransmit
io.ResetCollision := ~(StatePreamble | (StateData(0) | StateData(1)) | StatePAD | StateFCS)
val ExcessiveDeferOccured = io.TxStartFrm & StateDefer & ExcessiveDefer & ~StopExcessiveDeferOccured
io.StartTxDone := ~io.Collision & (StateFCS & NibCntEq7 | StateData(1) & io.TxEndFrm & (~io.Pad | io.Pad & NibbleMinFl) & ~io.CrcEn)
io.LateCollision := StartJam & ~ColWindow
io.MaxCollisionOccured := StartJam & ColWindow;
StateSFD := StatePreamble & NibCntEq15;
io.StartTxAbort := ExcessiveDeferOccured | io.LateCollision | io.MaxCollisionOccured
when(~io.TxStartFrm){
StopExcessiveDeferOccured := false.B
}.elsewhen(ExcessiveDeferOccured){
StopExcessiveDeferOccured := true.B
}
// Collision Window
when(~io.Collision & ByteCnt(5,0) === io.CollValid & (StateData(1) | StatePAD & NibCnt.extract(0) | StateFCS & NibCnt.extract(0))){
ColWindow := false.B
} .elsewhen(StateIdle | StateIPG){
ColWindow := true.B
}
// Start Window
when(~io.TxStartFrm){
StatusLatch := false.B
} .elsewhen(ExcessiveDeferOccured | StateIdle){
StatusLatch := true.B
}
// Transmit packet done
when(io.TxStartFrm & ~StatusLatch){
TxDone := false.B
}.elsewhen(io.StartTxDone){
TxDone := true.B
}
// Transmit packet abort
when(io.TxStartFrm & ~StatusLatch & ~ExcessiveDeferOccured){
TxAbort := false.B
} .elsewhen(io.StartTxAbort){
TxAbort := true.B
}
when( true.B ){
MTxD := // Transmit nibble
Mux(
StateData(0), io.TxData(3,0), // Lower nibble
Mux(StateData(1), io.TxData(7,4), // Higher nibble
Mux( StateFCS, Cat(~Crc.extract(28), ~Crc.extract(29), ~Crc.extract(30), ~Crc.extract(31)), // Crc
Mux(StateJam, 9.U, // Jam pattern
Mux(
StatePreamble, Mux(NibCntEq15, "hd".U, 5.U),// SFD,Preamble
0.U
)
)
)
)
)
}
val PacketFinished_d = io.StartTxDone | io.LateCollision | io.MaxCollisionOccured | ExcessiveDeferOccured;
val PacketFinished = RegNext(PacketFinished_d, false.B)
when(true.B){
PacketFinished_q := PacketFinished
}
}