未完成,尝试建立DMA
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
|
||||
|
||||
package MAC
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
|
||||
val write = Input(Bool())
|
||||
val read = Input(Bool())
|
||||
val clear = Input(Bool())
|
||||
val data_in = Input(UInt(dw.W))
|
||||
|
||||
val data_out = Output(UInt(dw.W))
|
||||
val almost_full = Output(Bool())
|
||||
val full = Output(Bool())
|
||||
val almost_empty = Output(Bool())
|
||||
val empty = Output(Bool())
|
||||
|
||||
|
||||
val cnt = Output(UInt(cntw.W))
|
||||
|
||||
|
||||
class AsyncFifo(dw: Int, aw: Int) extends RawModule{
|
||||
|
||||
def dp: Int = { var res = 1; for ( i <- 0 until aw ) { res = res * 2 }; return res }
|
||||
|
||||
class AsyncFifoIO extends Bundle{
|
||||
val clockEnq = Input(Bool())
|
||||
val clockDeq = Input(Bool())
|
||||
val resetEnq = Input(Bool())
|
||||
val resetDeq = Input(Bool())
|
||||
|
||||
val enq = Flipped(Decoupled(UInt(dw.W)))
|
||||
val deq = Decoupled( UInt(dw.W) )
|
||||
|
||||
val almost_full = Output(Bool())
|
||||
val almost_empty = Output(Bool())
|
||||
|
||||
def full = ~enq.ready
|
||||
def empty = ~deq.valid
|
||||
|
||||
}
|
||||
|
||||
val io: AsyncFifoIO = IO(new AsyncFifoIO)
|
||||
|
||||
val fifo = withClockAndReset( io.clockEnq.asClock, io.reset ) (Mem( dp, UInt(dw.W) ))
|
||||
|
||||
|
||||
val wrPtr = withClockAndReset( io.clockEnq.asClock, io.resetEnq ) (RegInit(0.U((aw+1).W)))
|
||||
val wrPrtGray = BinaryToGray(wrPtr)
|
||||
|
||||
val rdPtr = withClockAndReset( io.clockDeq.asClock, io.resetDeq ) (RegInit(0.U((aw+1).W)))
|
||||
val rdPrtGray = BinaryToGray(rdPtr)
|
||||
|
||||
val wrPrtGraySync = withClockAndReset( io.clockDeq.asClock, io.resetDeq ) ( ShiftRegister( wrPrtGray, 2, 0.U, true.B ) )
|
||||
val rdPrtGraySync = withClockAndReset( io.clockEnq.asClock, io.resetEnq ) ( ShiftRegister( rdPrtGray, 2, 0.U, true.B ) )
|
||||
|
||||
val isEmpty = wrPrtGraySync === rdPrtGray
|
||||
val isFull = (wrPrtGray(aw-2, 0) === rdPrtGraySync(aw-2, 0)) & (wrPrtGray.extract(aw-1) =/= rdPrtGraySync.extract(aw-1))
|
||||
|
||||
io.enq.ready := ~isFull
|
||||
io.deq.valid := ~isEmpty
|
||||
|
||||
withClockAndReset( io.clockEnq.asClock, io.resetEnq ){
|
||||
when( io.enq.fire ){
|
||||
fifo(wrPtr) := io.enq.bits
|
||||
}
|
||||
}
|
||||
|
||||
io.deq.bits := fifo(rdPtr)
|
||||
|
||||
|
||||
}
|
||||
379
src/main/scala/Switch/mac/MacRx.scala
Normal file
379
src/main/scala/Switch/mac/MacRx.scala
Normal file
@@ -0,0 +1,379 @@
|
||||
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)
|
||||
|
||||
}
|
||||
479
src/main/scala/Switch/mac/MacTx.scala
Normal file
479
src/main/scala/Switch/mac/MacTx.scala
Normal file
@@ -0,0 +1,479 @@
|
||||
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 HugEn = Input(Bool()) // Huge packets enable (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 MaxRet = Input(UInt(4.W)) // Maximum retry number (from register)
|
||||
val NoBckof = Input(Bool()) // No backoff (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 TxRetry = Output(Bool()) // Transmit packet retry (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 RetryCnt = Output(UInt(4.W)) // Latched Retry Counter for tx status purposes
|
||||
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 StartBackoff = Wire(Bool())
|
||||
|
||||
|
||||
|
||||
|
||||
val StateSFD = Wire(Bool())
|
||||
|
||||
val TooBig = Wire(Bool())
|
||||
|
||||
val CrcError = Wire(Bool())
|
||||
|
||||
|
||||
val NibbleMinFl = Wire(Bool())
|
||||
val ExcessiveDefer = Wire(Bool())
|
||||
|
||||
val MaxFrame = Wire(Bool())
|
||||
val RetryMax = Wire(Bool())
|
||||
val RandomEq0 = Wire(Bool())
|
||||
val RandomEqByteCnt = 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 StateBackOff = RegInit(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
|
||||
|
||||
val RetryCnt = RegInit(0.U(4.W)); io.RetryCnt := RetryCnt
|
||||
}
|
||||
|
||||
|
||||
|
||||
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) & ~MaxFrame
|
||||
|
||||
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)
|
||||
|
||||
StartBackoff := StateJam & ~RandomEq0 & ColWindow & ~RetryMax & NibCntEq7 & ~io.NoBckof
|
||||
|
||||
StartDefer :=
|
||||
(StateIPG & ~Rule1 & io.CarrierSense & NibCnt(6,0) <= io.IPGR1 & NibCnt(6,0) =/= io.IPGR2) |
|
||||
(StateIdle & io.CarrierSense) |
|
||||
(StateJam & NibCntEq7 & (io.NoBckof | RandomEq0 | ~ColWindow | RetryMax)) |
|
||||
(StateBackOff & (RandomEqByteCnt)) |
|
||||
io.StartTxDone |
|
||||
TooBig
|
||||
|
||||
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(StartBackoff | StartDefer){
|
||||
StateJam := false.B
|
||||
} .elsewhen(StartJam){
|
||||
StateJam := true.B
|
||||
}
|
||||
|
||||
when(StartDefer){
|
||||
StateBackOff := false.B
|
||||
} .elsewhen(StartBackoff){
|
||||
StateBackOff := true.B
|
||||
}
|
||||
|
||||
when(StartIPG){
|
||||
StateDefer := false.B
|
||||
} .elsewhen(StartDefer){
|
||||
StateDefer := true.B
|
||||
}
|
||||
|
||||
// This sections defines which interpack gap rule to use
|
||||
when(StateIdle | StateBackOff){
|
||||
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 | StateBackOff |
|
||||
(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) |
|
||||
(StateBackOff & (NibCnt(6,0) === 127.U)) |
|
||||
((StatePAD | StateFCS) & NibCnt.extract(0) & ~ByteCntMax)
|
||||
|
||||
val ResetByteCnt =
|
||||
StartBackoff |
|
||||
(StateIdle & io.TxStartFrm) |
|
||||
PacketFinished_q
|
||||
|
||||
|
||||
ByteCntMax := ByteCnt.andR
|
||||
when(ResetByteCnt){
|
||||
ByteCnt := 0.U
|
||||
} .elsewhen(IncrementByteCnt){
|
||||
ByteCnt := ByteCnt + 1.U
|
||||
}
|
||||
|
||||
MaxFrame := (ByteCnt === io.MaxFL) & ~io.HugEn;
|
||||
|
||||
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
|
||||
|
||||
|
||||
}
|
||||
|
||||
trait MacTxRandom{ this: MacTxBase =>
|
||||
|
||||
val x = RegInit(0.U(10.W))
|
||||
when(true.B){
|
||||
x := Cat( x(8,0), ~(x.extract(2) ^ x.extract(9)) )
|
||||
}
|
||||
|
||||
val RandomLatched = RegEnable(
|
||||
Cat(
|
||||
Mux( RetryCnt > 9.U, x.extract(9), 0.U(1.W)),
|
||||
Mux( RetryCnt > 8.U, x.extract(8), 0.U(1.W)),
|
||||
Mux( RetryCnt > 7.U, x.extract(7), 0.U(1.W)),
|
||||
Mux( RetryCnt > 6.U, x.extract(6), 0.U(1.W)),
|
||||
Mux( RetryCnt > 5.U, x.extract(5), 0.U(1.W)),
|
||||
Mux( RetryCnt > 4.U, x.extract(4), 0.U(1.W)),
|
||||
Mux( RetryCnt > 3.U, x.extract(3), 0.U(1.W)),
|
||||
Mux( RetryCnt > 2.U, x.extract(2), 0.U(1.W)),
|
||||
Mux( RetryCnt > 1.U, x.extract(1), 0.U(1.W)),
|
||||
x.extract(0)
|
||||
),
|
||||
0.U(10.W),
|
||||
StateJam & StateJam_q
|
||||
)
|
||||
|
||||
// Random Number == 0 IEEE 802.3 page 68. If 0 we go to defer and not to backoff.
|
||||
RandomEq0 := RandomLatched === 0.U
|
||||
RandomEqByteCnt := ByteCnt(9,0) === RandomLatched & (NibCnt(6,0).andR)
|
||||
|
||||
}
|
||||
|
||||
class MacTx extends MacTxBase with MacTxFSM with MacTxCounter with MacTxCRC with MacTxRandom{
|
||||
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 TxRetry = RegInit(false.B); io.TxRetry := TxRetry
|
||||
val TxAbort = RegInit(false.B); io.TxAbort := TxAbort
|
||||
|
||||
val MTxEn = RegNext(StatePreamble | (StateData(0) | StateData(1)) | StatePAD | StateFCS | StateJam, false.B); io.MTxEn := MTxEn
|
||||
val MTxErr = RegNext( TooBig, false.B); io.MTxErr := MTxErr// Transmit error
|
||||
|
||||
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)
|
||||
TooBig := ~io.Collision & MaxFrame & (StateData(0) | StateFCS);
|
||||
val StartTxRetry = StartJam & (ColWindow & ~RetryMax)
|
||||
io.LateCollision := StartJam & ~ColWindow
|
||||
io.MaxCollisionOccured := StartJam & ColWindow & RetryMax;
|
||||
StateSFD := StatePreamble & NibCntEq15;
|
||||
io.StartTxAbort := TooBig | 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 retry
|
||||
when(io.TxStartFrm & ~StatusLatch){
|
||||
TxRetry := false.B
|
||||
} .elsewhen(StartTxRetry){
|
||||
TxRetry := true.B
|
||||
}
|
||||
|
||||
|
||||
// Transmit packet abort
|
||||
when(io.TxStartFrm & ~StatusLatch & ~ExcessiveDeferOccured){
|
||||
TxAbort := false.B
|
||||
} .elsewhen(io.StartTxAbort){
|
||||
TxAbort := true.B
|
||||
}
|
||||
|
||||
// Retry counter
|
||||
when(ExcessiveDeferOccured | TooBig | io.StartTxDone
|
||||
| StateJam & NibCntEq7 & (~ColWindow | RetryMax)){
|
||||
RetryCnt := 0.U
|
||||
}.elsewhen(StateJam & NibCntEq7 & ColWindow & (RandomEq0 | io.NoBckof) | StateBackOff & RandomEqByteCnt){
|
||||
RetryCnt := RetryCnt + 1.U
|
||||
}
|
||||
|
||||
RetryMax := RetryCnt === io.MaxRet
|
||||
|
||||
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 | TooBig | io.LateCollision | io.MaxCollisionOccured | ExcessiveDeferOccured;
|
||||
val PacketFinished = RegNext(PacketFinished_d, false.B)
|
||||
when(true.B){
|
||||
PacketFinished_q := PacketFinished
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
package Switch
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
class Receive_Enq_Ctrl_Bundle extends Bundle{
|
||||
val LatchedRxLength = UInt(16.W)
|
||||
val RxStatusInLatched = UInt(9.W)
|
||||
val isRxAbort = Bool()
|
||||
}
|
||||
|
||||
class Receive_Deq_Ctrl_Bundle extends Bundle{
|
||||
|
||||
}
|
||||
|
||||
class Receive_Enq_Bundle extends Bundle{
|
||||
val data = Decoupled(UInt(32.W))
|
||||
val ctrl = Decoupled(new Receive_Enq_Ctrl_Bundle)
|
||||
}
|
||||
|
||||
|
||||
class Receive_Deq_Bundle extends Bundle{
|
||||
val data = Decoupled(UInt(32.W))
|
||||
val ctrl = Decoupled(new Receive_Deq_Ctrl_Bundle)
|
||||
}
|
||||
|
||||
|
||||
class RxBuffIO extends Bundle{
|
||||
val enq = Flipped(new Receive_Enq_Bundle)
|
||||
val deq = new Receive_Deq_Bundle
|
||||
}
|
||||
|
||||
|
||||
class Packet_Info_Bundle extends Bundle{
|
||||
val LatchedRxLength = UInt(16.W)
|
||||
val RxStatusInLatched = UInt(9.W)
|
||||
val header = Vec( 5, UInt(32.W) )
|
||||
}
|
||||
|
||||
|
||||
class RxBuff extends Module{
|
||||
val io: RxBuffIO = IO(new RxBuffIO)
|
||||
|
||||
val isPing = RegInit(true.B)
|
||||
val isPong = ~isPing
|
||||
|
||||
val pipoBuff = for( i <- 0 until 2 ) yield { Module(new Queue( UInt(32.W), 2048/4 )) }
|
||||
val pipoInfo = for( i <- 0 until 2 ) yield { Reg(new Packet_Info_Bundle) }
|
||||
dontTouch(pipoBuff(0).io.enq)
|
||||
dontTouch(pipoInfo(0))
|
||||
dontTouch(pipoBuff(1).io.enq)
|
||||
dontTouch(pipoInfo(1))
|
||||
|
||||
val recCnt = RegInit(0.U(3.W))
|
||||
|
||||
pipoBuff(0).io.enq.valid := isPing & io.enq.data.valid
|
||||
pipoBuff(0).io.enq.bits := io.enq.data.bits
|
||||
|
||||
pipoBuff(1).io.enq.valid := isPong & io.enq.data.valid
|
||||
pipoBuff(1).io.enq.bits := io.enq.data.bits
|
||||
|
||||
io.enq.data.ready := (isPing & pipoBuff(0).io.enq.ready) | (isPong & pipoBuff(1).io.enq.ready)
|
||||
io.enq.ctrl.ready := true.B
|
||||
|
||||
pipoBuff(0).reset := reset.asBool | (isPing & io.enq.ctrl.fire & io.enq.ctrl.bits.isRxAbort)
|
||||
pipoBuff(1).reset := reset.asBool | (isPong & io.enq.ctrl.fire & io.enq.ctrl.bits.isRxAbort)
|
||||
|
||||
when( io.enq.ctrl.fire & ~io.enq.ctrl.bits.isRxAbort){
|
||||
isPing := ~isPing
|
||||
when( isPing ){
|
||||
pipoInfo(0).LatchedRxLength := io.enq.ctrl.bits.LatchedRxLength
|
||||
pipoInfo(0).RxStatusInLatched := io.enq.ctrl.bits.RxStatusInLatched
|
||||
} .elsewhen( isPong ){
|
||||
pipoInfo(1).LatchedRxLength := io.enq.ctrl.bits.LatchedRxLength
|
||||
pipoInfo(1).RxStatusInLatched := io.enq.ctrl.bits.RxStatusInLatched
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
when( io.enq.ctrl.fire ){
|
||||
recCnt := 0.U
|
||||
} .elsewhen( io.enq.data.fire ){
|
||||
when( recCnt < 5.U ){
|
||||
recCnt := recCnt + 1.U
|
||||
when( isPing ){
|
||||
pipoInfo(0).header(recCnt) := io.enq.data.bits
|
||||
} .elsewhen( isPong ){
|
||||
pipoInfo(1).header(recCnt) := io.enq.data.bits
|
||||
} .otherwise{
|
||||
assert(false.B, "Assert Failed, Rx Under Run")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pipoBuff(0).io.deq.ready := false.B
|
||||
pipoBuff(1).io.deq.ready := false.B
|
||||
|
||||
io.deq.data.valid := false.B
|
||||
io.deq.data.bits := 0.U
|
||||
|
||||
io.deq.ctrl.valid := false.B
|
||||
io.deq.ctrl.bits := 0.U.asTypeOf(new Receive_Deq_Ctrl_Bundle)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package Switch
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
|
||||
class Transmit_Enq_Ctrl_Bundle extends Bundle{
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Transmit_Deq_Req_Bundle extends Bundle{
|
||||
val txLength = UInt(16.W)
|
||||
val PerPacketCrcEn = Bool()
|
||||
val PerPacketPad = Bool()
|
||||
}
|
||||
|
||||
class Transmit_Deq_Resp_Bundle extends Bundle{
|
||||
val RetryCntLatched = UInt(4.W)
|
||||
val RetryLimit = Bool()
|
||||
val LateCollLatched = Bool()
|
||||
val DeferLatched = Bool()
|
||||
val CarrierSenseLost = Bool()
|
||||
|
||||
val isClear = Bool()
|
||||
}
|
||||
|
||||
class Transmit_Enq_Bundle extends Bundle{
|
||||
val data = Decoupled(UInt(32.W))
|
||||
val ctrl = Decoupled(new Transmit_Enq_Ctrl_Bundle)
|
||||
}
|
||||
|
||||
|
||||
class Transmit_Deq_Bundle extends Bundle{
|
||||
val data = Decoupled(UInt(32.W))
|
||||
val req = Decoupled(new Transmit_Deq_Req_Bundle)
|
||||
val resp = Flipped(Decoupled(new Transmit_Deq_Resp_Bundle))
|
||||
}
|
||||
|
||||
|
||||
class TxBuffIO extends Bundle{
|
||||
val enq = Flipped(new Transmit_Enq_Bundle)
|
||||
val deq = new Transmit_Deq_Bundle
|
||||
}
|
||||
|
||||
|
||||
class TxBuff extends Module{
|
||||
val io: TxBuffIO = IO(new TxBuffIO)
|
||||
|
||||
io.enq.data.ready := true.B
|
||||
io.enq.ctrl.ready := true.B
|
||||
|
||||
io.deq.data.valid := false.B
|
||||
io.deq.data.bits := 0.U
|
||||
|
||||
io.deq.req.valid := false.B
|
||||
io.deq.req.bits := 0.U.asTypeOf(new Transmit_Deq_Req_Bundle)
|
||||
|
||||
io.deq.resp.ready := true.B
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user