未完成,尝试建立DMA

This commit is contained in:
RuigeLee
2023-10-19 18:31:26 +08:00
parent 70922ecb44
commit c5f9b4d74f
9 changed files with 349 additions and 211 deletions

View File

@@ -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)
}

View 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)
}

View 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
}
}

View File

@@ -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)
}

View File

@@ -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
}