拓扑修改,编译通过

This commit is contained in:
RuigeLee
2023-10-19 15:24:26 +08:00
parent d77c69aa5a
commit 70922ecb44
22 changed files with 303 additions and 228 deletions

View File

@@ -0,0 +1,74 @@
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,853 @@
package MAC
import chisel3._
import chisel3.util._
import Switch._
class MII extends Bundle with MDIO{
// Tx
val mtx_clk_pad_i = Input(Bool())
val mtxd_pad_o = Output(UInt(4.W))
val mtxen_pad_o = Output(Bool())
val mtxerr_pad_o = Output(Bool())
// Rx
val mrx_clk_pad_i = Input(Bool())
val mrxd_pad_i = Input(UInt(4.W))
val mrxdv_pad_i = Input(Bool())
val mrxerr_pad_i = Input(Bool())
// Common Tx and Rx
val mcoll_pad_i = Input(Bool())
val mcrs_pad_i = Input(Bool())
}
class MacIO extends Bundle{
val mii = new MII
val cfg = Flipped(new Mac_Config_Bundle)
val rxEnq = new Receive_Enq_Bundle
val txDeq = Flipped(new Transmit_Deq_Bundle)
// val int_o = Output(Bool())
val isLoopBack = Output(Bool())
val asyncReset = Input(AsyncReset())
}
class Mac extends Module{
val io = IO(new MacIO)
val r_ClkDiv = Wire(UInt(8.W))
val r_MiiNoPre = Wire(Bool())
val r_CtrlData = Wire(UInt(16.W))
val r_FIAD = Wire(UInt(5.W))
val r_RGAD = Wire(UInt(5.W))
val r_WCtrlData = Wire(Bool())
val r_RStat = Wire(Bool())
val r_ScanStat = Wire(Bool())
val NValid_stat = Wire(Bool())
val Busy_stat = Wire(Bool())
val LinkFail = Wire(Bool())
val Prsd = Wire(UInt(16.W))
val WCtrlDataStart = Wire(Bool())
val RStatStart = Wire(Bool())
val UpdateMIIRX_DATAReg = Wire(Bool())
dontTouch( r_ClkDiv )
dontTouch( r_MiiNoPre )
dontTouch( r_CtrlData )
dontTouch( r_FIAD )
dontTouch( r_RGAD )
dontTouch( r_WCtrlData )
dontTouch( r_RStat )
dontTouch( r_ScanStat )
dontTouch( NValid_stat )
dontTouch( Busy_stat )
dontTouch( LinkFail )
dontTouch( Prsd )
dontTouch( WCtrlDataStart )
dontTouch( RStatStart )
dontTouch( UpdateMIIRX_DATAReg )
val TxStartFrm = Wire(Bool())
val TxEndFrm = Wire(Bool())
val TxUsedData = Wire(Bool())
val TxData = Wire(UInt(8.W))
val TxRetry = Wire(Bool())
val TxAbort = Wire(Bool())
val TxDone = Wire(Bool())
val TPauseRq = Wire(Bool())
dontTouch(TxStartFrm)
dontTouch(TxEndFrm )
dontTouch(TxUsedData)
dontTouch(TxData )
dontTouch(TxRetry )
dontTouch(TxAbort )
dontTouch(TxDone )
dontTouch(TPauseRq )
val RstTxPauseRq = RegInit(false.B)
// Connecting Miim module
val miim = Module(new MIIM)
miim.io.Divider := r_ClkDiv
miim.io.NoPre := r_MiiNoPre
miim.io.WCtrlData := r_WCtrlData
miim.io.CtrlData := r_CtrlData
miim.io.Fiad := r_FIAD
miim.io.Rgad := r_RGAD
miim.io.RStat := r_RStat
miim.io.ScanStat := r_ScanStat
miim.io.mdi := io.mii.mdi
Busy_stat := miim.io.Busy
LinkFail := miim.io.LinkFail
NValid_stat := miim.io.Nvalid
Prsd := miim.io.Prsd
WCtrlDataStart := miim.io.WCtrlDataStart
RStatStart := miim.io.RStatStart
UpdateMIIRX_DATAReg := miim.io.UpdateMIIRX_DATAReg
io.mii.mdc := miim.io.mdc
io.mii.mdo := miim.io.mdo
io.mii.mdoEn := miim.io.mdoEn
val r_RecSmall = Wire(Bool())
val r_LoopBck = Wire(Bool())
val r_TxEn = Wire(Bool())
val r_RxEn = Wire(Bool())
val MRxDV_Lb = Wire(Bool())
val MRxErr_Lb = Wire(Bool())
val MRxD_Lb = Wire(UInt(4.W))
val Transmitting = Wire(Bool())
val r_HugEn = Wire(Bool())
val r_DlyCrcEn = Wire(Bool())
val r_MaxFL = Wire(UInt(16.W))
val r_MinFL = Wire(UInt(16.W))
val ShortFrame = Wire(Bool())
val DribbleNibble = Wire(Bool())
val ReceivedPacketTooBig = Wire(Bool())
val r_MAC = Wire(UInt(48.W))
val LoadRxStatus = Wire(Bool())
val r_HASH0 = Wire(UInt(32.W))
val r_HASH1 = Wire(UInt(32.W))
val r_TxBDNum = Wire(UInt(8.W))
val r_IPGT = Wire(UInt(7.W))
val r_IPGR1 = Wire(UInt(7.W))
val r_IPGR2 = Wire(UInt(7.W))
val r_CollValid = Wire(UInt(6.W))
val r_TxPauseTV = Wire(UInt(16.W))
val r_TxPauseRq = Wire(Bool())
val r_MaxRet = Wire(UInt(4.W))
val r_NoBckof = Wire(Bool())
val r_ExDfrEn = Wire(Bool())
val r_TxFlow = Wire(Bool())
val r_IFG = Wire(Bool())
val TxB_IRQ = Wire(Bool())
val TxE_IRQ = Wire(Bool())
val RxB_IRQ = Wire(Bool())
val RxE_IRQ = Wire(Bool())
val Busy_IRQ = Wire(Bool())
val r_Pad = Wire(Bool())
val r_CrcEn = Wire(Bool())
val r_FullD = Wire(Bool())
val r_Pro = Wire(Bool())
val r_Bro = Wire(Bool())
val r_NoPre = Wire(Bool())
val r_RxFlow = Wire(Bool())
val r_PassAll = Wire(Bool())
val TxCtrlEndFrm = Wire(Bool())
val StartTxDone = Wire(Bool())
val SetPauseTimer = Wire(Bool())
val TxUsedDataIn = Wire(Bool())
val TxDoneIn = Wire(Bool())
val TxAbortIn = Wire(Bool())
val PerPacketPad = Wire(Bool())
val PadOut = Wire(Bool())
val PerPacketCrcEn = Wire(Bool())
val CrcEnOut = Wire(Bool())
val TxStartFrmOut = Wire(Bool())
val TxEndFrmOut = Wire(Bool())
val ReceivedPauseFrm = Wire(Bool())
val ControlFrmAddressOK = Wire(Bool())
val RxStatusWriteLatchedSync = Wire(Bool())
val LateCollision = Wire(Bool())
val DeferIndication = Wire(Bool())
val LateCollLatched = Wire(Bool())
val DeferLatched = Wire(Bool())
val RstDeferLatched = Wire(Bool())
val CarrierSenseLost = Wire(Bool())
dontTouch(r_RecSmall )
dontTouch(r_LoopBck )
dontTouch(r_TxEn )
dontTouch(r_RxEn )
dontTouch(MRxDV_Lb )
dontTouch(MRxErr_Lb )
dontTouch(MRxD_Lb )
dontTouch(Transmitting )
dontTouch(r_HugEn )
dontTouch(r_DlyCrcEn )
dontTouch(r_MaxFL )
dontTouch(r_MinFL )
dontTouch(ShortFrame )
dontTouch(DribbleNibble )
dontTouch(ReceivedPacketTooBig )
dontTouch(r_MAC )
dontTouch(LoadRxStatus )
dontTouch(r_HASH0 )
dontTouch(r_HASH1 )
dontTouch(r_TxBDNum )
dontTouch(r_IPGT )
dontTouch(r_IPGR1 )
dontTouch(r_IPGR2 )
dontTouch(r_CollValid )
dontTouch(r_TxPauseTV )
dontTouch(r_TxPauseRq )
dontTouch(r_MaxRet )
dontTouch(r_NoBckof )
dontTouch(r_ExDfrEn )
dontTouch(r_TxFlow )
dontTouch(r_IFG )
dontTouch(TxB_IRQ )
dontTouch(TxE_IRQ )
dontTouch(RxB_IRQ )
dontTouch(RxE_IRQ )
dontTouch(Busy_IRQ )
dontTouch(r_Pad )
dontTouch(r_CrcEn )
dontTouch(r_FullD )
dontTouch(r_Pro )
dontTouch(r_Bro )
dontTouch(r_NoPre )
dontTouch(r_RxFlow )
dontTouch(r_PassAll )
dontTouch(TxCtrlEndFrm )
dontTouch(StartTxDone )
dontTouch(SetPauseTimer )
dontTouch(TxUsedDataIn )
dontTouch(TxDoneIn )
dontTouch(TxAbortIn )
dontTouch(PerPacketPad )
dontTouch(PadOut )
dontTouch(PerPacketCrcEn )
dontTouch(CrcEnOut )
dontTouch(TxStartFrmOut )
dontTouch(TxEndFrmOut )
dontTouch(ReceivedPauseFrm )
dontTouch(ControlFrmAddressOK )
dontTouch(RxStatusWriteLatchedSync )
dontTouch(LateCollision )
dontTouch(DeferIndication )
dontTouch(LateCollLatched )
dontTouch(DeferLatched )
dontTouch(RstDeferLatched )
dontTouch(CarrierSenseLost )
// val ethReg = Module(new MacReg(outer.configNode))
io.cfg.WCtrlDataStart := WCtrlDataStart
io.cfg.RStatStart := RStatStart
io.cfg.UpdateMIIRX_DATAReg := UpdateMIIRX_DATAReg
io.cfg.Prsd := Prsd
io.cfg.NValid_stat := NValid_stat
io.cfg.Busy_stat := Busy_stat
io.cfg.LinkFail := LinkFail
io.cfg.TxB_IRQ := TxB_IRQ
io.cfg.TxE_IRQ := TxE_IRQ
io.cfg.RxB_IRQ := RxB_IRQ
io.cfg.RxE_IRQ := RxE_IRQ
io.cfg.Busy_IRQ := Busy_IRQ
io.cfg.RstTxPauseRq := RstTxPauseRq
io.cfg.TxCtrlEndFrm := TxCtrlEndFrm
io.cfg.StartTxDone := StartTxDone
io.cfg.TxClk := io.mii.mtx_clk_pad_i
io.cfg.RxClk := io.mii.mrx_clk_pad_i
io.cfg.SetPauseTimer := SetPauseTimer
r_RecSmall := io.cfg.r_RecSmall
r_Pad := io.cfg.r_Pad
r_HugEn := io.cfg.r_HugEn
r_CrcEn := io.cfg.r_CrcEn
r_DlyCrcEn := io.cfg.r_DlyCrcEn
r_FullD := io.cfg.r_FullD
r_ExDfrEn := io.cfg.r_ExDfrEn
r_NoBckof := io.cfg.r_NoBckof
r_LoopBck := io.cfg.r_LoopBck
r_IFG := io.cfg.r_IFG
r_Pro := io.cfg.r_Pro
r_Bro := io.cfg.r_Bro
r_NoPre := io.cfg.r_NoPre
r_TxEn := io.cfg.r_TxEn
r_RxEn := io.cfg.r_RxEn
r_HASH0 := io.cfg.r_HASH0
r_HASH1 := io.cfg.r_HASH1
r_IPGT := io.cfg.r_IPGT
r_IPGR1 := io.cfg.r_IPGR1
r_IPGR2 := io.cfg.r_IPGR2
r_MinFL := io.cfg.r_MinFL
r_MaxFL := io.cfg.r_MaxFL
r_MaxRet := io.cfg.r_MaxRet
r_CollValid := io.cfg.r_CollValid
r_TxFlow := io.cfg.r_TxFlow
r_RxFlow := io.cfg.r_RxFlow
r_PassAll := io.cfg.r_PassAll
r_MiiNoPre := io.cfg.r_MiiNoPre
r_ClkDiv := io.cfg.r_ClkDiv
r_WCtrlData := io.cfg.r_WCtrlData
r_RStat := io.cfg.r_RStat
r_ScanStat := io.cfg.r_ScanStat
r_RGAD := io.cfg.r_RGAD
r_FIAD := io.cfg.r_FIAD
r_CtrlData := io.cfg.r_CtrlData
r_MAC := io.cfg.r_MAC
r_TxBDNum := io.cfg.r_TxBDNum
r_TxPauseTV := io.cfg.r_TxPauseTV
r_TxPauseRq := io.cfg.r_TxPauseRq
val RxData = Wire(UInt(8.W))
val RxValid = Wire(Bool())
val RxStartFrm = Wire(Bool())
val RxEndFrm = Wire(Bool())
val RxAbort = Wire(Bool())
val WillTransmit = Wire(Bool())
val ResetCollision = Wire(Bool())
val TxDataOut = Wire(UInt(8.W))
val WillSendControlFrame = Wire(Bool())
val ReceiveEnd = Wire(Bool())
val ReceivedPacketGood = Wire(Bool())
val ReceivedLengthOK = Wire(Bool())
val InvalidSymbol = Wire(Bool())
val LatchedCrcError = Wire(Bool())
val RxLateCollision = Wire(Bool())
val RetryCntLatched = Wire(UInt(4.W))
val RetryCnt = Wire(UInt(4.W))
val StartTxAbort = Wire(Bool())
val MaxCollisionOccured = Wire(Bool())
val RetryLimit = Wire(Bool())
val StatePreamble = Wire(Bool())
val StateData = Wire(UInt(2.W))
dontTouch(RxData )
dontTouch(RxValid )
dontTouch(RxStartFrm )
dontTouch(RxEndFrm )
dontTouch(RxAbort )
dontTouch(WillTransmit )
dontTouch(ResetCollision )
dontTouch(TxDataOut )
dontTouch(WillSendControlFrame)
dontTouch(ReceiveEnd )
dontTouch(ReceivedPacketGood )
dontTouch(ReceivedLengthOK )
dontTouch(InvalidSymbol )
dontTouch(LatchedCrcError )
dontTouch(RxLateCollision )
dontTouch(RetryCntLatched )
dontTouch(RetryCnt )
dontTouch(StartTxAbort )
dontTouch(MaxCollisionOccured )
dontTouch(RetryLimit )
dontTouch(StatePreamble )
dontTouch(StateData )
// Connecting MACControl
val maccontrol = Module(new MacControl)
maccontrol.io.MTxClk := io.mii.mtx_clk_pad_i
maccontrol.io.MRxClk := io.mii.mrx_clk_pad_i
maccontrol.io.asyncReset := io.asyncReset
maccontrol.io.TPauseRq := TPauseRq
maccontrol.io.TxDataIn := TxData
maccontrol.io.TxStartFrmIn := TxStartFrm
maccontrol.io.TxUsedDataIn := TxUsedDataIn
maccontrol.io.TxEndFrmIn := TxEndFrm
maccontrol.io.TxDoneIn := TxDoneIn
maccontrol.io.TxAbortIn := TxAbortIn
maccontrol.io.PadIn := r_Pad | PerPacketPad
maccontrol.io.CrcEnIn := r_CrcEn | PerPacketCrcEn
maccontrol.io.RxData := RxData
maccontrol.io.RxValid := RxValid
maccontrol.io.RxStartFrm := RxStartFrm
maccontrol.io.RxEndFrm := RxEndFrm
maccontrol.io.ReceiveEnd := ReceiveEnd
maccontrol.io.ReceivedPacketGood := ReceivedPacketGood
maccontrol.io.ReceivedLengthOK := ReceivedLengthOK
maccontrol.io.TxFlow := r_TxFlow
maccontrol.io.RxFlow := r_RxFlow
maccontrol.io.DlyCrcEn := r_DlyCrcEn
maccontrol.io.TxPauseTV := r_TxPauseTV
maccontrol.io.MAC := r_MAC
maccontrol.io.RxStatusWriteLatched_sync2 := RxStatusWriteLatchedSync
maccontrol.io.r_PassAll := r_PassAll
TxDataOut := maccontrol.io.TxDataOut
TxStartFrmOut := maccontrol.io.TxStartFrmOut
TxEndFrmOut := maccontrol.io.TxEndFrmOut
TxDone := maccontrol.io.TxDoneOut
TxAbort := maccontrol.io.TxAbortOut
TxUsedData := maccontrol.io.TxUsedDataOut
PadOut := maccontrol.io.PadOut
CrcEnOut := maccontrol.io.CrcEnOut
WillSendControlFrame := maccontrol.io.WillSendControlFrame
TxCtrlEndFrm := maccontrol.io.TxCtrlEndFrm
ReceivedPauseFrm := maccontrol.io.ReceivedPauseFrm
ControlFrmAddressOK := maccontrol.io.ControlFrmAddressOK
SetPauseTimer := maccontrol.io.SetPauseTimer
val TxCarrierSense = Wire(Bool())
val Collision = Wire(Bool())
val CarrierSense_Tx2 = Wire(Bool())
val RxEnSync = Wire(Bool())
dontTouch(TxCarrierSense )
dontTouch(Collision )
dontTouch(CarrierSense_Tx2)
dontTouch(RxEnSync )
io.isLoopBack := r_LoopBck
// Muxed MII receive data valid
MRxDV_Lb := Mux(r_LoopBck, io.mii.mtxen_pad_o, io.mii.mrxdv_pad_i & RxEnSync)
// Muxed MII Receive Error
MRxErr_Lb := Mux(r_LoopBck, io.mii.mtxerr_pad_o, io.mii.mrxerr_pad_i & RxEnSync)
// Muxed MII Receive Data
MRxD_Lb := Mux(r_LoopBck, io.mii.mtxd_pad_o, io.mii.mrxd_pad_i)
val txethmac = withClockAndReset(io.mii.mtx_clk_pad_i.asClock, io.asyncReset)( Module(new MacTx))
txethmac.io.TxStartFrm := TxStartFrmOut
txethmac.io.TxEndFrm := TxEndFrmOut
txethmac.io.TxData := TxDataOut
txethmac.io.CarrierSense := TxCarrierSense
txethmac.io.Collision := Collision
txethmac.io.Pad := PadOut
txethmac.io.CrcEn := CrcEnOut
txethmac.io.FullD := r_FullD
txethmac.io.HugEn := r_HugEn
txethmac.io.DlyCrcEn := r_DlyCrcEn
txethmac.io.MinFL := r_MinFL
txethmac.io.MaxFL := r_MaxFL
txethmac.io.IPGT := r_IPGT
txethmac.io.IPGR1 := r_IPGR1
txethmac.io.IPGR2 := r_IPGR2
txethmac.io.CollValid := r_CollValid
txethmac.io.MaxRet := r_MaxRet
txethmac.io.NoBckof := r_NoBckof
txethmac.io.ExDfrEn := r_ExDfrEn
io.mii.mtxd_pad_o := txethmac.io.MTxD
io.mii.mtxen_pad_o := txethmac.io.MTxEn
io.mii.mtxerr_pad_o := txethmac.io.MTxErr
TxDoneIn := txethmac.io.TxDone
TxRetry := txethmac.io.TxRetry
TxAbortIn := txethmac.io.TxAbort
TxUsedDataIn := txethmac.io.TxUsedData
WillTransmit := txethmac.io.WillTransmit
ResetCollision := txethmac.io.ResetCollision
RetryCnt := txethmac.io.RetryCnt
StartTxDone := txethmac.io.StartTxDone
StartTxAbort := txethmac.io.StartTxAbort
MaxCollisionOccured := txethmac.io.MaxCollisionOccured
LateCollision := txethmac.io.LateCollision
DeferIndication := txethmac.io.DeferIndication
StatePreamble := txethmac.io.StatePreamble
StateData := txethmac.io.StateData
val RxByteCnt = Wire(UInt(16.W))
val RxByteCntEq0 = Wire(Bool())
val RxByteCntGreat2 = Wire(Bool())
val RxByteCntMaxFrame = Wire(Bool())
val RxCrcError = Wire(Bool())
val RxStateIdle = Wire(Bool())
val RxStatePreamble = Wire(Bool())
val RxStateSFD = Wire(Bool())
val RxStateData = Wire(UInt(2.W))
val AddressMiss = Wire(Bool())
dontTouch(RxByteCnt )
dontTouch(RxByteCntEq0 )
dontTouch(RxByteCntGreat2 )
dontTouch(RxByteCntMaxFrame)
dontTouch(RxCrcError )
dontTouch(RxStateIdle )
dontTouch(RxStatePreamble )
dontTouch(RxStateSFD )
dontTouch(RxStateData )
dontTouch(AddressMiss )
val rxethmac = withClockAndReset(io.mii.mrx_clk_pad_i.asClock, io.asyncReset)( Module(new MacRx))
rxethmac.io.MRxDV := MRxDV_Lb
rxethmac.io.MRxD := MRxD_Lb
rxethmac.io.Transmitting := Transmitting
rxethmac.io.HugEn := r_HugEn
rxethmac.io.DlyCrcEn := r_DlyCrcEn
rxethmac.io.MaxFL := r_MaxFL
rxethmac.io.r_IFG := r_IFG
rxethmac.io.MAC := r_MAC
rxethmac.io.r_Bro := r_Bro
rxethmac.io.r_Pro := r_Pro
rxethmac.io.r_HASH0 := r_HASH0
rxethmac.io.r_HASH1 := r_HASH1
rxethmac.io.PassAll := r_PassAll
rxethmac.io.ControlFrmAddressOK := ControlFrmAddressOK
RxData := rxethmac.io.RxData
RxValid := rxethmac.io.RxValid
RxStartFrm := rxethmac.io.RxStartFrm
RxEndFrm := rxethmac.io.RxEndFrm
RxByteCnt := rxethmac.io.ByteCnt
RxByteCntEq0 := rxethmac.io.ByteCntEq0
RxByteCntGreat2 := rxethmac.io.ByteCntGreat2
RxByteCntMaxFrame := rxethmac.io.ByteCntMaxFrame
RxCrcError := rxethmac.io.CrcError
RxStateIdle := rxethmac.io.StateIdle
RxStatePreamble := rxethmac.io.StatePreamble
RxStateSFD := rxethmac.io.StateSFD
RxStateData := rxethmac.io.StateData
RxAbort := rxethmac.io.RxAbort
AddressMiss := rxethmac.io.AddressMiss
withClockAndReset( io.mii.mtx_clk_pad_i.asClock, reset.asAsyncReset ) {
// MII Carrier Sense Synchronization
CarrierSense_Tx2 := ShiftRegister(io.mii.mcrs_pad_i, 2, false.B, true.B)
TxCarrierSense := ~r_FullD & CarrierSense_Tx2
val Collision_Tx1 = RegNext(io.mii.mcoll_pad_i, false.B)
val Collision_Tx2 = RegInit(false.B)
when(ResetCollision){
Collision_Tx2 := false.B
} .elsewhen(Collision_Tx1){
Collision_Tx2 := true.B
}
// Synchronized Collision
Collision := ~r_FullD & Collision_Tx2
}
withClockAndReset( io.mii.mrx_clk_pad_i.asClock, reset.asAsyncReset ) {
val WillTransmit_q = ShiftRegister(WillTransmit, 2, false.B, true.B)
Transmitting := ~r_FullD & WillTransmit_q
RxEnSync := RegEnable( ShiftRegister(r_RxEn, 2), false.B, ~io.mii.mrxdv_pad_i)
}
// Synchronizing WillSendControlFrame to WB_CLK;
val WillSendControlFrame_sync = ShiftRegisters(WillSendControlFrame, 3, false.B, true.B)
when(true.B){
RstTxPauseRq := WillSendControlFrame_sync(1) & ~WillSendControlFrame_sync(2)
}
withClockAndReset( io.mii.mtx_clk_pad_i.asClock, reset.asAsyncReset ) {
val TxPauseRq_sync = ShiftRegisters((r_TxPauseRq & r_TxFlow), 3, false.B, true.B )
TPauseRq := RegNext( TxPauseRq_sync(1) & (~TxPauseRq_sync(2)), false.B )
}
val LatchedMRxErr = Wire(Bool())
val RxAbort_latch_wire = Wire(Bool())
val RxAbort_wb = ShiftRegister( RxAbort_latch_wire, 2, false.B, true.B )
withClockAndReset( io.mii.mrx_clk_pad_i.asClock, reset.asAsyncReset ) {
val RxAbort_latch = RegInit(false.B); RxAbort_latch_wire := RxAbort_latch
val RxAbortRst = ShiftRegister( RxAbort_wb, 2, false.B, true.B )
// Synchronizing RxAbort to the WISHBONE clock
when(RxAbort | (ShortFrame & ~r_RecSmall) | LatchedMRxErr & ~InvalidSymbol | (ReceivedPauseFrm & (~r_PassAll))){
RxAbort_latch := true.B
} .elsewhen(RxAbortRst){
RxAbort_latch := false.B
}
}
val wishbone = Module(new MacTileLink)
wishbone.io.RetryCntLatched := RetryCntLatched
wishbone.io.RetryLimit := RetryLimit
wishbone.io.LateCollLatched := LateCollLatched
wishbone.io.DeferLatched := DeferLatched
wishbone.io.CarrierSenseLost := CarrierSenseLost
PerPacketCrcEn := wishbone.io.PerPacketCrcEn
PerPacketPad := wishbone.io.PerPacketPad
wishbone.io.r_TxEn := r_TxEn
wishbone.io.r_RxEn := r_RxEn
TxB_IRQ := false.B
TxE_IRQ := false.B
RxB_IRQ := false.B
RxE_IRQ := false.B
val macstatus = Module(new MacStatus)
macstatus.io.asyncReset := io.asyncReset
macstatus.io.MRxClk := io.mii.mrx_clk_pad_i
macstatus.io.RxCrcError := RxCrcError
macstatus.io.MRxErr := MRxErr_Lb
macstatus.io.MRxDV := MRxDV_Lb
macstatus.io.RxStateSFD := RxStateSFD
macstatus.io.RxStateData := RxStateData
macstatus.io.RxStatePreamble := RxStatePreamble
macstatus.io.RxStateIdle := RxStateIdle
macstatus.io.Transmitting := Transmitting
macstatus.io.RxByteCnt := RxByteCnt
macstatus.io.RxByteCntEq0 := RxByteCntEq0
macstatus.io.RxByteCntGreat2 := RxByteCntGreat2
macstatus.io.RxByteCntMaxFrame := RxByteCntMaxFrame
macstatus.io.MRxD := MRxD_Lb
macstatus.io.Collision := io.mii.mcoll_pad_i
macstatus.io.CollValid := r_CollValid
macstatus.io.r_RecSmall := r_RecSmall
macstatus.io.r_MinFL := r_MinFL
macstatus.io.r_MaxFL := r_MaxFL
macstatus.io.r_HugEn := r_HugEn
macstatus.io.StartTxDone := StartTxDone
macstatus.io.StartTxAbort := StartTxAbort
macstatus.io.RetryCnt := RetryCnt
macstatus.io.MTxClk := io.mii.mtx_clk_pad_i
macstatus.io.MaxCollisionOccured := MaxCollisionOccured
macstatus.io.LateCollision := LateCollision
macstatus.io.DeferIndication := DeferIndication
macstatus.io.TxStartFrm := TxStartFrmOut
macstatus.io.StatePreamble := StatePreamble
macstatus.io.StateData := StateData
macstatus.io.CarrierSense := CarrierSense_Tx2
macstatus.io.TxUsedData := TxUsedDataIn
macstatus.io.Loopback := r_LoopBck
macstatus.io.r_FullD := r_FullD
macstatus.io.RstDeferLatched := RstDeferLatched
ReceivedLengthOK := macstatus.io.ReceivedLengthOK
ReceiveEnd := macstatus.io.ReceiveEnd
ReceivedPacketGood := macstatus.io.ReceivedPacketGood
InvalidSymbol := macstatus.io.InvalidSymbol
LatchedCrcError := macstatus.io.LatchedCrcError
RxLateCollision := macstatus.io.RxLateCollision
ShortFrame := macstatus.io.ShortFrame
DribbleNibble := macstatus.io.DribbleNibble
ReceivedPacketTooBig := macstatus.io.ReceivedPacketTooBig
LoadRxStatus := macstatus.io.LoadRxStatus
RetryCntLatched := macstatus.io.RetryCntLatched
RetryLimit := macstatus.io.RetryLimit
LateCollLatched := macstatus.io.LateCollLatched
DeferLatched := macstatus.io.DeferLatched
CarrierSenseLost := macstatus.io.CarrierSenseLost
LatchedMRxErr := macstatus.io.LatchedMRxErr
val macTileLinkTx = withClockAndReset( io.mii.mtx_clk_pad_i.asClock, io.asyncReset ) (Module(new MacTileLinkTx))
// Start: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I
val ReadTxDataFromFifo_sync = ShiftRegister( macTileLinkTx.io.ReadTxDataFromFifo_tck, 2, false.B, true.B)
wishbone.io.ReadTxDataFromFifo_sync := ReadTxDataFromFifo_sync
withClockAndReset( io.mii.mtx_clk_pad_i.asClock, io.asyncReset ){
macTileLinkTx.io.BlockingTxStatusWrite_sync := ShiftRegister( wishbone.io.BlockingTxStatusWrite, 2, false.B, true.B)
macTileLinkTx.io.TxStartFrm_sync := ShiftRegister( wishbone.io.TxStartFrm_wb, 2, false.B, true.B ) // Synchronizing TxStartFrm_wb to MTxClk
macTileLinkTx.io.ReadTxDataFromFifo_syncb := ShiftRegister( ReadTxDataFromFifo_sync, 2, false.B, true.B)
}
wishbone.io.TxStartFrm_syncb := ShiftRegister( macTileLinkTx.io.TxStartFrm_sync, 2, false.B, true.B )
RstDeferLatched := macTileLinkTx.io.RstDeferLatched
TxStartFrm := macTileLinkTx.io.TxStartFrm
TxEndFrm := macTileLinkTx.io.TxEndFrm
TxData := macTileLinkTx.io.TxData
macTileLinkTx.io.TxData_wb := wishbone.io.TxData_wb
macTileLinkTx.io.TxValidBytesLatched := wishbone.io.TxValidBytesLatched
macTileLinkTx.io.TxEndFrm_wb := wishbone.io.TxEndFrm_wb
wishbone.io.TxUsedData := TxUsedData
macTileLinkTx.io.TxUsedData := TxUsedData
macTileLinkTx.io.TxRetry := TxRetry
macTileLinkTx.io.TxAbort := TxAbort
macTileLinkTx.io.TxDone := TxDone
wishbone.io.TxRetrySync := ShiftRegister( TxRetry, 2, false.B, true.B )
wishbone.io.TxAbortSync := ShiftRegister( TxAbort, 2, false.B, true.B )
wishbone.io.TxDoneSync := ShiftRegister( TxDone, 2, false.B, true.B )
val macTileLinkRx = withClockAndReset( io.mii.mrx_clk_pad_i.asClock, io.asyncReset ) ( Module(new MacTileLinkRx) )
wishbone.io.RxDataLatched2_rxclk := macTileLinkRx.io.RxDataLatched2
val WriteRxDataToFifoSync = ShiftRegister(macTileLinkRx.io.WriteRxDataToFifo, 2, false.B, true.B)
wishbone.io.WriteRxDataToFifoSync := WriteRxDataToFifoSync
val RxAbortSync = ShiftRegister( macTileLinkRx.io.RxAbortLatched, 2, false.B, true.B )
wishbone.io.RxAbortSync := RxAbortSync
val ShiftEndedSync = ShiftRegister( macTileLinkRx.io.ShiftEnded_rck, 2, false.B, true.B )
wishbone.io.ShiftEndedSync := ShiftEndedSync
wishbone.io.LatchedRxLength_rxclk := macTileLinkRx.io.LatchedRxLength
wishbone.io.RxStatusInLatched_rxclk := macTileLinkRx.io.RxStatusInLatched
// Busy Interrupt
val Busy_IRQ_sync = ShiftRegister(macTileLinkRx.io.Busy_IRQ_rck, 2, false.B, true.B)
Busy_IRQ := Busy_IRQ_sync & ~RegNext(Busy_IRQ_sync, false.B)
withClockAndReset( io.mii.mrx_clk_pad_i.asClock, io.asyncReset ) {
val ShiftEndedSyncb = ShiftRegister( ShiftEndedSync, 2, false.B, true.B)
RxStatusWriteLatchedSync := ShiftEndedSyncb
macTileLinkRx.io.ShiftEndedSyncb := ShiftEndedSyncb
macTileLinkRx.io.RxAbortSyncb := ShiftRegister( RxAbortSync, 2, false.B, true.B )
macTileLinkRx.io.Busy_IRQ_syncb := ShiftRegister( Busy_IRQ_sync, 2, false.B, true.B )
macTileLinkRx.io.WriteRxDataToFifoSyncb := ShiftRegister( WriteRxDataToFifoSync, 2, false.B, true.B )
macTileLinkRx.io.RxReady := ShiftRegister( wishbone.io.RxReady, 2, false.B, true.B )
}
macTileLinkRx.io.RxData := RxData
macTileLinkRx.io.RxAbort := RxAbort_latch_wire
macTileLinkRx.io.RxValid := RxValid
macTileLinkRx.io.RxStartFrm := RxStartFrm
macTileLinkRx.io.RxEndFrm := RxEndFrm
macTileLinkRx.io.RxLength := RxByteCnt
macTileLinkRx.io.LoadRxStatus := LoadRxStatus
macTileLinkRx.io.RxStatusIn := Cat(ReceivedPauseFrm, AddressMiss, false.B, InvalidSymbol, DribbleNibble, ReceivedPacketTooBig, ShortFrame, LatchedCrcError, RxLateCollision)
wishbone.io.rxEnq <> io.rxEnq
wishbone.io.txDeq <> io.txDeq
}

View File

@@ -0,0 +1,239 @@
package MAC
import chisel3._
import chisel3.util._
class MIIMIO extends Bundle with MDIO{
val Divider = Input( UInt(8.W) ) // Divider for the host clock // Divider (input clock will be divided by the Divider[7:0])
val NoPre = Input(Bool()) // No Preamble (no 32-bit preamble)
val WCtrlData = Input(Bool()) // Write Control Data operation
val CtrlData = Input( UInt(16.W) ) // Control Data (to be written to the PHY reg.)
val Fiad = Input( UInt(5.W) ) // PHY Address
val Rgad = Input(UInt(5.W)) // Register Address (within the PHY)
val RStat = Input( Bool() ) // Read Status operation
val ScanStat = Input( Bool() ) // Scan Status operation
val Busy = Output(Bool()) // Busy Signal
val LinkFail = Output(Bool()) // Link Integrity Signal
val Nvalid = Output(Bool()) // Invalid Status (qualifier for the valid scan result)
val Prsd = Output(UInt(16.W)) // Read Status Data (data read from the PHY)
val WCtrlDataStart = Output(Bool()) // This signals resets the WCTRLDATA bit in the MIIM Command register
val RStatStart = Output(Bool()) // This signal resets the RSTAT BIT in the MIIM Command register
val UpdateMIIRX_DATAReg = Output(Bool()) // Updates MII RX_DATA register with read data
}
class MIIMBase extends Module{
val io: MIIMIO = IO(new MIIMIO)
val ByteSelect = Wire( Vec( 4, Bool() ) ) // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register.
// Counter counts half period
val Counter = RegInit( 1.U(8.W) )
val mdc = RegInit(false.B) // Output clock
val mdcEn = (Counter === 0.U) & ~mdc // Enable signal is asserted for one Clk period before mdc rises.
val mdcEn_n = (Counter === 0.U) & mdc // Enable signal is asserted for one Clk period before mdc falls.
val ShiftReg = RegInit(0.U(8.W)) // Shift register for shifting the data in and out
val Prsd = RegInit(0.U(16.W))
val LinkFail = RegInit(false.B)
val BitCounter = RegInit( 0.U(7.W) ) // Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted)
val EndOp = BitCounter === 63.U // Operation ends when the Bit Counter reaches 63
val InProgress = RegInit(false.B) // Operation in progress
val InProgress_q = ShiftRegisters(InProgress, 3, false.B, mdcEn) // Operation in progress delayed 3 mdc cycles
val EndBusy = ShiftRegister(~InProgress_q(1) & InProgress_q(2), 2, false.B, true.B) // Generation of the EndBusy signal. It is used for ending the MII Management operation.
val WriteOp = RegInit(false.B) // Write Operation Latch (When asserted, write operation is in progress)
io.mdc := mdc
io.LinkFail := LinkFail
io.Prsd := Prsd
}
/** Connecting the Clock Generator Module */
trait MIIMClockGen{ this: MIIMBase =>
val TempDivider = Mux( io.Divider < 2.U, 2.U, io.Divider ) // If smaller than 2
val CounterPreset = ( TempDivider >> 1 ) - 1.U // We are counting half of period
when( Counter === 0.U ) {
mdc := ~mdc // mdc is asserted every other half period
Counter := CounterPreset
} .otherwise{
Counter := Counter - 1.U
}
}
trait MIIMShiftReg{ this: MIIMBase =>
val LatchByte0 = ShiftRegister(InProgress & ~WriteOp & BitCounter === "h3F".U, 2, false.B, mdcEn) // Latch Byte selects which part of Read Status Data is updated from the shift register
val LatchByte1 = ShiftRegister(InProgress & ~WriteOp & BitCounter === "h37".U, 2, false.B, mdcEn) // Latch Byte selects which part of Read Status Data is updated from the shift register
ByteSelect(0) := InProgress & ((io.NoPre & (BitCounter === 0.U)) | (~io.NoPre & (BitCounter === "h20".U)));
ByteSelect(1) := InProgress & (BitCounter === "h28".U);
ByteSelect(2) := InProgress & WriteOp & (BitCounter === "h30".U);
ByteSelect(3) := InProgress & WriteOp & (BitCounter === "h38".U);
when(mdcEn_n){
when(ByteSelect.reduce(_|_)) {
ShiftReg := Mux1H(Seq(
ByteSelect(0) -> Cat("b01".U(2.W), ~WriteOp, WriteOp, io.Fiad(4,1)),
ByteSelect(1) -> Cat(io.Fiad.extract(0), io.Rgad(4,0), "b10".U(2.W)),
ByteSelect(2) -> io.CtrlData(15,8),
ByteSelect(3) -> io.CtrlData( 7,0),
))
} .otherwise{
ShiftReg := Cat(ShiftReg(6,0), io.mdi)
when(LatchByte0){
Prsd := Cat(Prsd(15,8), ShiftReg(6,0), io.mdi)
when(io.Rgad === 1.U){
LinkFail := ~ShiftReg.extract(1) // this is bit [2], because it is not shifted yet
}
} .elsewhen(LatchByte1){
Prsd := Cat(ShiftReg(6,0), io.mdi, Prsd(7,0))
}
}
}
}
trait MIIMOutputCtl{ this: MIIMBase =>
// Generation of the Serial Enable signal (enables the serialization of the data)
val SerialEn = ( WriteOp & InProgress & ( BitCounter > 31.U | ( ( BitCounter === 0.U ) & io.NoPre ) )) |
(~WriteOp & InProgress & (( BitCounter > 31.U & BitCounter < 46.U ) | ( ( BitCounter === 0.U ) & io.NoPre )))
val mdoEn = ShiftRegister( SerialEn | (InProgress & BitCounter<32.U), 3, false.B, mdcEn_n)
val mdo_2d = RegEnable( ~SerialEn & BitCounter<32.U, false.B, mdcEn_n)
val mdo_d = RegEnable( ShiftReg.extract(7) | mdo_2d, false.B, mdcEn_n)
val mdo = RegEnable( mdo_d, false.B, mdcEn_n)
io.mdo := mdo
io.mdoEn := mdoEn
}
class MIIM extends MIIMBase with MIIMClockGen with MIIMShiftReg with MIIMOutputCtl{
val WCtrlData_q = ShiftRegisters(io.WCtrlData, 3, false.B, true.B)
val WCtrlDataStart = RegInit(false.B) // Start Write Control Data Command (positive edge detected)
val WCtrlDataStart_q = ShiftRegisters(WCtrlDataStart, 2, false.B, mdcEn) // Start Write Control Data Command delayed 2 mdc cycle
val WriteDataOp = WCtrlDataStart_q(0) & ~WCtrlDataStart_q(1) // Write Data Operation (positive edge detected)
io.WCtrlDataStart := WCtrlDataStart
// Generation of the Operation signals
val StartOp = Wire(Bool()) // Start Operation (start of any of the preceding operations)
when( EndBusy ){
WCtrlDataStart := false.B
} .elsewhen( WCtrlData_q(1) & ~WCtrlData_q(2) ){
WCtrlDataStart := true.B
}
// Update MII RX_DATA register
val WCtrlDataStart_q0 = RegEnable(WCtrlDataStart, false.B, ~EndBusy)
val UpdateMIIRX_DATAReg = RegNext(EndBusy & ~WCtrlDataStart_q0, false.B) // Updates MII RX_DATA register with read data
io.UpdateMIIRX_DATAReg := UpdateMIIRX_DATAReg
val RStat_q = ShiftRegisters(io.RStat, 3, false.B, true.B)
val RStatStart = RegInit(false.B) // Start Read Status Command (positive edge detected)
val RStatStart_q = ShiftRegisters(RStatStart, 2, false.B, mdcEn) // Start Read Status Command delayed 2 mdc cycles
val ReadStatusOp = RStatStart_q(0) & ~RStatStart_q(1) // Read Status Operation (positive edge detected)
io.RStatStart := RStatStart
when( EndBusy ){
RStatStart := false.B
} .elsewhen(RStat_q(1) & ~RStat_q(2)){
RStatStart := true.B
}
when(mdcEn){
when(StartOp) {
InProgress := true.B
} .elsewhen(EndOp) {
InProgress := false.B
}
}
val ScanStat_q = ShiftRegisters(io.ScanStat, 2, false.B, true.B)
val SyncStatmdcEn = RegEnable(ScanStat_q(1), false.B, mdcEn) // Scan Status operation delayed at least cycles and synchronized to mdcEn
val ScanStatusOp = SyncStatmdcEn & ~InProgress & ~InProgress_q(0) & ~InProgress_q(1) // Scan Status Operation (positive edge detected)
val Nvalid = RegInit(false.B) // Generation of the Nvalid signal (indicates when the status is invalid)
io.Nvalid := Nvalid
when( ~InProgress_q(1) & InProgress_q(2) ) {
Nvalid := false.B
} .elsewhen(ScanStat_q(1) & ~SyncStatmdcEn) {
Nvalid := true.B
}
when(mdcEn){
when(StartOp) {
when( ~InProgress ){
WriteOp := Mux( WriteDataOp, true.B, false.B )
}
} .elsewhen(EndOp) {
WriteOp := false.B
}
}
when( mdcEn ){
when( InProgress ) {
when( io.NoPre & BitCounter === 0.U ) {
BitCounter := "h21".U
} .otherwise {
BitCounter := BitCounter + 1.U
}
} .otherwise {
BitCounter := 0.U
}
}
StartOp := WriteDataOp | ReadStatusOp | ScanStatusOp
io.Busy := io.WCtrlData | WCtrlDataStart | io.RStat | RStatStart | SyncStatmdcEn | EndBusy | InProgress | InProgress_q(2) | Nvalid
}

View File

@@ -0,0 +1,78 @@
package MAC
import chisel3._
import chisel3.util._
class TxBuffDesc extends Bundle{
val len = UInt(16.W) //[31.16]
val rd = Bool() //[15]
val irq = Bool() //14
val wr = Bool() //13
val pad = Bool() //12
val crc = Bool() //11
val reserved1 = UInt(2.W) //10,9
val ur = Bool() //8
val rtry = UInt(4.W) //7 6 5 4
val rl = Bool() //3
val lc = Bool() //2
val df = Bool() //1
val cs = Bool() //0
}
class RxBuffDesc extends Bundle{
val len = UInt(16.W) //[31.16]
val e = Bool() //15
val irq = Bool() //14
val wrap = Bool() //13
val reserved1 = UInt(4.W) //12 11 10 9
val cf = Bool() //8
val m = Bool() //7
val or = Bool() //6
val is = Bool() //5
val dn = Bool() //4
val tl = Bool() //3
val sf = Bool() //2
val crc = Bool() //1
val lc = Bool() //0
}
class MacWishboneMasterIO extends Bundle{
val m_wb_adr_o = Output(UInt(32.W))
val m_wb_sel_o = Output(UInt(4.W))
val m_wb_we_o = Output(Bool())
val m_wb_dat_i = Input(UInt(32.W))
val m_wb_dat_o = Output(UInt(32.W))
val m_wb_cyc_o = Output(Bool())
val m_wb_stb_o = Output(Bool())
val m_wb_ack_i = Input(Bool())
val m_wb_err_i = Input(Bool())
val m_wb_cti_o = Output(UInt(3.W))
val m_wb_bte_o = Output(UInt(2.W))
}
class MacWishboneSlaveIO extends Bundle{
val WB_DAT_I = Input(UInt(32.W)) // WISHBONE data input
val WB_DAT_O = Output(UInt(32.W)) // WISHBONE data output
val WB_ADR_I = Input(UInt(12.W)) // WISHBONE address input
val WB_WE_I = Input(Bool()) // WISHBONE write enable input
val WB_SEL_I = Input(UInt(4.W)) // WISHBONE byte select input
val WB_CYC_I = Input(Bool()) // WISHBONE cycle input
val WB_STB_I = Input(Bool()) // WISHBONE strobe input
val WB_ACK_O = Output(Bool()) // WISHBONE acknowledge output
val WB_ERR_O = Output(Bool()) // WISHBONE error output
}
trait MDIO { this: Bundle =>
val mdi = Input( Bool()) // MII Management Data In
val mdc = Output(Bool()) // MII Management Data Clock
val mdo = Output(Bool()) // MII Management Data Output
val mdoEn = Output(Bool()) // MII Management Data Output Enable
}

View File

@@ -0,0 +1,448 @@
package MAC
import chisel3._
import chisel3.util._
class MacControlIO extends Bundle{
val MTxClk = Input(Bool()) // Transmit clock (from PHY)
val MRxClk = Input(Bool()) // Receive clock (from PHY)
val asyncReset = Input(AsyncReset())
val TPauseRq = Input(Bool()) // Transmit control frame (from host)
val TxDataIn = Input(UInt(8.W)) // Transmit packet data byte (from host)
val TxStartFrmIn = Input(Bool()) // Transmit packet start frame input (from host)
val TxUsedDataIn = Input(Bool()) // Transmit packet used data (from TxEthMAC)
val TxEndFrmIn = Input(Bool()) // Transmit packet end frame input (from host)
val TxDoneIn = Input(Bool()) // Transmit packet done (from TxEthMAC)
val TxAbortIn = Input(Bool()) // Transmit packet abort (input from TxEthMAC)
val PadIn = Input(Bool()) // Padding (input from registers)
val CrcEnIn = Input(Bool()) // Crc append (input from registers)
val RxData = Input(UInt(8.W)) // Receive Packet Data (from RxEthMAC)
val RxValid = Input(Bool()) // Received a valid packet
val RxStartFrm = Input(Bool()) // Receive packet start frame (input from RxEthMAC)
val RxEndFrm = Input(Bool()) // Receive packet end frame (input from RxEthMAC)
val ReceiveEnd = Input(Bool()) // End of receiving of the current packet (input from RxEthMAC)
val ReceivedPacketGood = Input(Bool()) // Received packet is good
val ReceivedLengthOK = Input(Bool()) // Length of the received packet is OK
val TxFlow = Input(Bool()) // Tx flow control (from registers)
val RxFlow = Input(Bool()) // Rx flow control (from registers)
val DlyCrcEn = Input(Bool()) // Delayed CRC enabled (from registers)
val TxPauseTV = Input(UInt(16.W)) // Transmit Pause Timer Value (from registers)
val MAC = Input(UInt(48.W)) // MAC address (from registers)
val RxStatusWriteLatched_sync2 = Input(Bool())
val r_PassAll = Input(Bool())
val TxDataOut = Output(UInt(8.W)) // Transmit Packet Data (to TxEthMAC)
val TxStartFrmOut = Output(Bool()) // Transmit packet start frame (output to TxEthMAC)
val TxEndFrmOut = Output(Bool()) // Transmit packet end frame (output to TxEthMAC)
val TxDoneOut = Output(Bool()) // Transmit packet done (to host)
val TxAbortOut = Output(Bool()) // Transmit packet aborted (to host)
val TxUsedDataOut = Output(Bool()) // Transmit packet used data (to host)
val PadOut = Output(Bool()) // Padding (output to TxEthMAC)
val CrcEnOut = Output(Bool()) // Crc append (output to TxEthMAC)
val WillSendControlFrame = Output(Bool())
val TxCtrlEndFrm = Output(Bool())
val ReceivedPauseFrm = Output(Bool())
val ControlFrmAddressOK = Output(Bool())
val SetPauseTimer = Output(Bool())
}
class MacControl extends RawModule{
val io: MacControlIO = IO(new MacControlIO)
val Pause_wire = Wire(Bool())
val SlotFinished = Wire(Bool())
// Reserved multicast address and Type/Length for PAUSE control
val ReservedMulticast = "h0180C2000001".U(48.W)
val TypeLength = "h8808".U(16.W)
val DecrementPauseTimer = Wire(Bool())
val PauseTimerEq0 = Wire(Bool())
val ControlEnd = Wire(Bool())
val MuxedCtrlData = Wire(UInt(8.W))
val EnableCnt = Wire(Bool())
withClockAndReset( io.MTxClk.asClock, io.asyncReset ) {
val BlockTxDone = RegInit(false.B)
val SendingCtrlFrm = RegInit(false.B) // Sending Control Frame (enables padding and CRC)
val CtrlMux = RegInit(false.B)
val ControlData = RegInit(0.U(8.W))
val TxCtrlStartFrm = RegInit(false.B)
val DlyCrcCnt = RegInit(0.U(4.W))
val ByteCnt = RegInit(0.U(6.W))
val ControlEnd_q = RegNext(ControlEnd)
val TxCtrlStartFrm_q = RegNext(TxCtrlStartFrm)
val TxCtrlEndFrm = RegNext(ControlEnd | ControlEnd_q, false.B); io.TxCtrlEndFrm := TxCtrlEndFrm // Generation of the transmit control packet end frame
val TxUsedDataIn_q = RegNext(io.TxUsedDataIn, false.B)
val WillSendControlFrame = RegInit(false.B); io.WillSendControlFrame := WillSendControlFrame // A command for Sending the control frame is active (latched)
val TxUsedDataOutDetected = RegInit(false.B)
// Synchronization of the pause timer
val PauseTimerEq0_sync1 = RegNext(PauseTimerEq0, true.B)
val PauseTimerEq0_sync2 = RegNext(PauseTimerEq0_sync1, true.B)
val Pause = RegInit(false.B); Pause_wire := Pause // Pause signal generation
when((io.TxDoneIn | io.TxAbortIn | ~TxUsedDataOutDetected) & ~io.TxStartFrmOut){
Pause := io.RxFlow & ~PauseTimerEq0_sync2
}
// Signal TxUsedDataOut was detected (a transfer is already in progress)
when(io.TxDoneIn | io.TxAbortIn){
TxUsedDataOutDetected := false.B
} .elsewhen(io.TxUsedDataOut){
TxUsedDataOutDetected := true.B
}
// Latching variables
val TxAbortInLatched = RegNext(io.TxAbortIn, false.B)
val TxDoneInLatched = RegNext(io.TxDoneIn, false.B)
val MuxedAbort = RegInit(false.B) // Generating muxed abort signal
when(io.TxStartFrmIn){
MuxedAbort := false.B
} .elsewhen(io.TxAbortIn & ~TxAbortInLatched & TxUsedDataOutDetected){
MuxedAbort := true.B
}
val MuxedDone = RegInit(false.B) // Generating muxed done signal
when(io.TxStartFrmIn){
MuxedDone := false.B
} .elsewhen(io.TxDoneIn & (~TxDoneInLatched) & TxUsedDataOutDetected){
MuxedDone := true.B
}
when(TxCtrlEndFrm & CtrlMux){
WillSendControlFrame := false.B
} .elsewhen(io.TPauseRq & io.TxFlow){
WillSendControlFrame := true.B
}
// Generation of the transmit control packet start frame
when(TxUsedDataIn_q & CtrlMux){
TxCtrlStartFrm := false.B
} .elsewhen(WillSendControlFrame & ~io.TxUsedDataOut & (io.TxDoneIn | io.TxAbortIn | io.TxStartFrmIn | (~TxUsedDataOutDetected))){
TxCtrlStartFrm := true.B
}
// Generation of the multiplexer signal (controls muxes for switching between
// normal and control packets)
when(WillSendControlFrame & ~io.TxUsedDataOut){
CtrlMux := true.B
} .elsewhen(io.TxDoneIn){
CtrlMux := false.B
}
// Generation of the Sending Control Frame signal (enables padding and CRC)
when(WillSendControlFrame & TxCtrlStartFrm){
SendingCtrlFrm := true.B
} .elsewhen(io.TxDoneIn){
SendingCtrlFrm := false.B
}
// Generation of the signal that will block sending the Done signal to the eth_wishbone module
// While sending the control frame
when(TxCtrlStartFrm){
BlockTxDone := true.B
} .elsewhen(io.TxStartFrmIn){
BlockTxDone := false.B
}
val IncrementDlyCrcCnt = CtrlMux & io.TxUsedDataIn & ~DlyCrcCnt.extract(2)
val ResetByteCnt = io.asyncReset.asBool | (~TxCtrlStartFrm & (io.TxDoneIn | io.TxAbortIn))
// Delayed CRC counter
when(ResetByteCnt){
DlyCrcCnt := 0.U
} .elsewhen(IncrementDlyCrcCnt){
DlyCrcCnt := DlyCrcCnt + 1.U
}
val IncrementByteCnt = CtrlMux & (TxCtrlStartFrm & ~TxCtrlStartFrm_q & ~io.TxUsedDataIn | io.TxUsedDataIn & ~ControlEnd)
val IncrementByteCntBy2 = CtrlMux & TxCtrlStartFrm & (~TxCtrlStartFrm_q) & io.TxUsedDataIn // When TxUsedDataIn and CtrlMux are set at the same time
EnableCnt := (~io.DlyCrcEn | io.DlyCrcEn & (DlyCrcCnt(1,0).andR))
// Byte counter
when(ResetByteCnt){
ByteCnt := 0.U
} .elsewhen(IncrementByteCntBy2 & EnableCnt){
ByteCnt := ByteCnt + 2.U
} .elsewhen(IncrementByteCnt & EnableCnt){
ByteCnt := ByteCnt + 1.U
}
ControlEnd := ByteCnt === "h22".U
MuxedCtrlData := // Control data generation (goes to the TxEthMAC module)
Mux1H(Seq(
(ByteCnt === 0.U) -> Mux(~io.DlyCrcEn | io.DlyCrcEn & (DlyCrcCnt(1,0).andR), 1.U, 0.U),
(ByteCnt === 2.U) -> "h80".U,
(ByteCnt === 4.U) -> "hC2".U,
(ByteCnt === 6.U) -> "h00".U,
(ByteCnt === 8.U) -> "h00".U,
(ByteCnt === 10.U) -> "h01".U,
(ByteCnt === 12.U) -> io.MAC(47,40),
(ByteCnt === 14.U) -> io.MAC(39,32),
(ByteCnt === 16.U) -> io.MAC(31,24),
(ByteCnt === 18.U) -> io.MAC(23,16),
(ByteCnt === 20.U) -> io.MAC(15, 8),
(ByteCnt === 22.U) -> io.MAC( 7, 0),
(ByteCnt === 24.U) -> "h88".U, // Type/Length
(ByteCnt === 26.U) -> "h08".U,
(ByteCnt === 28.U) -> "h00".U, // Opcode
(ByteCnt === 30.U) -> "h01".U,
(ByteCnt === 32.U) -> io.TxPauseTV(15,8), // Pause timer value
(ByteCnt === 34.U) -> io.TxPauseTV( 7,0),
))
// Latched Control data
when(~ByteCnt.extract(0)){
ControlData := MuxedCtrlData
}
io.TxDoneOut := Mux(CtrlMux, ((~io.TxStartFrmIn) & (~BlockTxDone) & MuxedDone), ((~io.TxStartFrmIn) & (~BlockTxDone) & io.TxDoneIn)) // TxDoneOut
io.TxAbortOut := Mux(CtrlMux, ((~io.TxStartFrmIn) & (~BlockTxDone) & MuxedAbort), ((~io.TxStartFrmIn) & (~BlockTxDone) & io.TxAbortIn)) // TxAbortOut
io.TxUsedDataOut := ~CtrlMux & io.TxUsedDataIn // TxUsedDataOut
io.TxStartFrmOut := Mux(CtrlMux, TxCtrlStartFrm, (io.TxStartFrmIn & ~Pause)) // TxStartFrmOut
io.TxEndFrmOut := Mux(CtrlMux, TxCtrlEndFrm, io.TxEndFrmIn) // TxEndFrmOut
io.TxDataOut := Mux(CtrlMux, ControlData, io.TxDataIn ) // TxDataOut[7:0]
io.PadOut := io.PadIn | SendingCtrlFrm // PadOut
io.CrcEnOut := io.CrcEnIn | SendingCtrlFrm // CrcEnOut
}
withClockAndReset( io.MRxClk.asClock, io.asyncReset.asAsyncReset ) {
val AddressOK = RegInit(false.B); io.ControlFrmAddressOK := AddressOK // Multicast or unicast address detected
val TypeLengthOK = RegInit(false.B) // Type/Length field contains 0x8808
val DetectionWindow = RegInit(true.B) // Detection of the PAUSE frame is possible within this window
val OpCodeOK = RegInit(false.B) // PAUSE opcode detected (0x0001)
val DlyCrcCnt = RegInit(0.U(3.W))
val ByteCnt = RegInit(0.U(5.W))
val AssembledTimerValue = RegInit(0.U(16.W))
val LatchedTimerValue = RegInit(0.U(16.W))
val ReceivedPauseFrmWAddr = RegInit(false.B)
val PauseTimer = RegInit(0.U(16.W))
val ByteCntEq0 = io.RxValid & ByteCnt === "h0".U
val ByteCntEq1 = io.RxValid & ByteCnt === "h1".U
val ByteCntEq2 = io.RxValid & ByteCnt === "h2".U
val ByteCntEq3 = io.RxValid & ByteCnt === "h3".U
val ByteCntEq4 = io.RxValid & ByteCnt === "h4".U
val ByteCntEq5 = io.RxValid & ByteCnt === "h5".U
val ByteCntEq12 = io.RxValid & ByteCnt === "h0C".U
val ByteCntEq13 = io.RxValid & ByteCnt === "h0D".U
val ByteCntEq14 = io.RxValid & ByteCnt === "h0E".U
val ByteCntEq15 = io.RxValid & ByteCnt === "h0F".U
val ByteCntEq16 = io.RxValid & ByteCnt === "h10".U
val ByteCntEq17 = io.RxValid & ByteCnt === "h11".U
val ByteCntEq18 = io.RxValid & ByteCnt === "h12".U & DetectionWindow
// Address Detection (Multicast or unicast)
when(DetectionWindow & ByteCntEq0){
AddressOK := io.RxData === ReservedMulticast(47,40) | io.RxData === io.MAC(47,40)
} .elsewhen(DetectionWindow & ByteCntEq1){
AddressOK := (io.RxData === ReservedMulticast(39,32) | io.RxData === io.MAC(39,32)) & AddressOK;
} .elsewhen(DetectionWindow & ByteCntEq2){
AddressOK := (io.RxData === ReservedMulticast(31,24) | io.RxData === io.MAC(31,24)) & AddressOK;
} .elsewhen(DetectionWindow & ByteCntEq3){
AddressOK := (io.RxData === ReservedMulticast(23,16) | io.RxData === io.MAC(23,16)) & AddressOK;
} .elsewhen(DetectionWindow & ByteCntEq4){
AddressOK := (io.RxData === ReservedMulticast(15,8) | io.RxData === io.MAC(15,8)) & AddressOK;
} .elsewhen(DetectionWindow & ByteCntEq5){
AddressOK := (io.RxData === ReservedMulticast(7,0) | io.RxData === io.MAC(7,0)) & AddressOK;
} .elsewhen(io.ReceiveEnd){
AddressOK := false.B
}
// TypeLengthOK (Type/Length Control frame detected)
when(DetectionWindow & ByteCntEq12){
TypeLengthOK := ByteCntEq12 & (io.RxData === TypeLength(15,8));
} .elsewhen(DetectionWindow & ByteCntEq13){
TypeLengthOK := ByteCntEq13 & (io.RxData === TypeLength(7,0)) & TypeLengthOK;
} .elsewhen(io.ReceiveEnd){
TypeLengthOK := false.B
}
// Latch Control Frame Opcode
when(ByteCntEq16){
OpCodeOK := false.B
} .otherwise{
when(DetectionWindow & ByteCntEq14){
OpCodeOK := ByteCntEq14 & io.RxData === 0.U
}
when(DetectionWindow & ByteCntEq15){
OpCodeOK := ByteCntEq15 & io.RxData === 1.U & OpCodeOK;
}
}
// ReceivedPauseFrmWAddr (+Address Check)
when(io.ReceiveEnd){
ReceivedPauseFrmWAddr := false.B
} .elsewhen(ByteCntEq16 & TypeLengthOK & OpCodeOK & AddressOK){
ReceivedPauseFrmWAddr := true.B
}
// Assembling 16-bit timer value from two 8-bit data
when(io.RxStartFrm){
AssembledTimerValue := 0.U
} .otherwise{
when(DetectionWindow & ByteCntEq16){
AssembledTimerValue := Cat(io.RxData, AssembledTimerValue(7,0))
}
when(DetectionWindow & ByteCntEq17){
AssembledTimerValue := Cat(AssembledTimerValue(15,8), io.RxData )
}
}
// Detection window (while PAUSE detection is possible)
when(ByteCntEq18){
DetectionWindow := false.B
} .elsewhen(io.ReceiveEnd){
DetectionWindow := true.B
}
// Latching Timer Value
when(DetectionWindow & ReceivedPauseFrmWAddr & ByteCntEq18){
LatchedTimerValue := AssembledTimerValue
} .elsewhen(io.ReceiveEnd){
LatchedTimerValue := 0.U
}
// Delayed CEC counter
when(io.RxValid & io.RxEndFrm){
DlyCrcCnt := 0.U
}.elsewhen(io.RxValid & ~io.RxEndFrm & ~DlyCrcCnt.extract(2)){
DlyCrcCnt := DlyCrcCnt + 1.U
}
val IncrementByteCnt =
io.RxValid & DetectionWindow & ~ByteCntEq18 &
(~io.DlyCrcEn | io.DlyCrcEn & DlyCrcCnt.extract(2))
// Byte counter
when(io.RxEndFrm){
ByteCnt := 0.U
} .elsewhen(IncrementByteCnt){
ByteCnt := ByteCnt + 1.U
}
when(io.SetPauseTimer){
PauseTimer := LatchedTimerValue
} .elsewhen(DecrementPauseTimer){
PauseTimer := PauseTimer - 1.U
}
val Divider2 = RegInit(false.B) // Divider2 is used for incrementing the Slot timer every other clock
when(PauseTimer.orR & io.RxFlow){
Divider2 := ~Divider2
} .otherwise{
Divider2 := false.B
}
val SlotTimer = RegInit(0.U(6.W)) // SlotTimer
when(io.asyncReset.asBool()){
SlotTimer := 0.U
} .elsewhen(Pause_wire & io.RxFlow & Divider2){
SlotTimer := SlotTimer + 1.U
}
val ReceivedPauseFrm = RegInit(false.B); io.ReceivedPauseFrm := ReceivedPauseFrm // Pause Frame received
when((io.RxStatusWriteLatched_sync2 & io.r_PassAll) | (ReceivedPauseFrm & (~io.r_PassAll))){
ReceivedPauseFrm := false.B
} .elsewhen(ByteCntEq16 & TypeLengthOK & OpCodeOK){
ReceivedPauseFrm := true.B
}
io.SetPauseTimer :=
io.ReceiveEnd & ReceivedPauseFrmWAddr & io.ReceivedPacketGood & io.ReceivedLengthOK & io.RxFlow
DecrementPauseTimer := SlotFinished & PauseTimer.orR
PauseTimerEq0 := ~PauseTimer.orR
SlotFinished := SlotTimer.andR & Pause_wire & io.RxFlow & Divider2 // Slot is 512 bits (64 bytes)
}
}

View File

@@ -0,0 +1,77 @@
package MAC
import chisel3._
import chisel3.util._
class MacFifoIO(dw: Int, cntw: Int) extends Bundle{
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 MacFifo(dw: Int, dp: Int) extends Module{
def cntw = log2Ceil(dp)+1
val io: MacFifoIO = IO(new MacFifoIO(dw, cntw ))
val fifo = Mem( dp, UInt(dw.W) )
val data_out = Reg(UInt(dw.W)); io.data_out := data_out
val cnt = RegInit( 0.U(cntw.W)); io.cnt := cnt
val read_pointer = RegInit(0.U(log2Ceil(dp).W))
val write_pointer = RegInit(0.U(log2Ceil(dp).W))
when(io.clear){
cnt := io.read ^ io.write
} .elsewhen(io.read ^ io.write){
when(io.read){
cnt := cnt - 1.U
} .otherwise{
cnt := cnt + 1.U
}
}
when(io.clear){
read_pointer := io.read
} .elsewhen(io.read & ~io.empty){
read_pointer := read_pointer + 1.U
}
when(io.clear){
write_pointer := io.write
} .elsewhen(io.write & ~io.full){
write_pointer := write_pointer + 1.U
}
io.empty := ~(cnt.orR)
io.almost_empty := cnt === 1.U
io.full := cnt === dp.U;
io.almost_full := cnt(cntw-2,0).andR
when(io.write & io.clear){
fifo.write(0.U, io.data_in)
} .elsewhen(io.write & ~io.full){
fifo.write(write_pointer, io.data_in)
}
when(io.clear){
data_out := fifo.read(0.U)
} .otherwise{
data_out := fifo.read(read_pointer)
}
}

View File

@@ -0,0 +1,58 @@
package MAC
import chisel3._
import chisel3.util._
class MacSRAMIO extends Bundle{
val we = Input(Vec(4, Bool())) // Write enable input, active high
val oe = Input(Bool()) // Output enable input, active high
val addr = Input(UInt(8.W)) // address bus inputs
val di = Input(UInt(32.W)) // input data bus
val dato = Output(UInt(32.W)) // output data bus
}
class MacSRAM extends Module{
val io: MacSRAMIO = IO(new MacSRAMIO)
// Generic RAM's registers and wires
val mem0 = Mem( 256, UInt(8.W) )
val mem1 = Mem( 256, UInt(8.W) )
val mem2 = Mem( 256, UInt(8.W) )
val mem3 = Mem( 256, UInt(8.W) )
val q = Wire(UInt(32.W))
val raddr = Reg( UInt(8.W) )
// Data output drivers
io.dato := Mux((io.oe), q, DontCare)
// read operation
when( true.B ){
raddr := io.addr // read address needs to be registered to read clock
}
q := Mux(reset.asBool, 0.U, Cat(mem3.read(raddr), mem2.read(raddr), mem1.read(raddr), mem0.read(raddr)))
// write operation
when(io.we(3)){
mem3.write(io.addr, io.di(31,24))
}
when(io.we(2)){
mem2.write(io.addr, io.di(23,16))
}
when(io.we(1)){
mem1.write(io.addr, io.di(15, 8))
}
when(io.we(0)){
mem0.write(io.addr, io.di( 7, 0))
}
}

View File

@@ -0,0 +1,180 @@
package MAC
import chisel3._
import chisel3.util._
class MacStatusIO extends Bundle{
val asyncReset = Input(AsyncReset())
val MRxClk = Input(Bool())
val RxCrcError = Input(Bool())
val MRxErr = Input(Bool())
val MRxDV = Input(Bool())
val RxStateSFD = Input(Bool())
val RxStateData = Input(UInt(2.W))
val RxStatePreamble = Input(Bool())
val RxStateIdle = Input(Bool())
val Transmitting = Input(Bool())
val RxByteCnt = Input(UInt(16.W))
val RxByteCntEq0 = Input(Bool())
val RxByteCntGreat2 = Input(Bool())
val RxByteCntMaxFrame = Input(Bool())
val MRxD = Input(UInt(4.W))
val Collision = Input(Bool())
val CollValid = Input(UInt(6.W))
val r_RecSmall = Input(Bool())
val r_MinFL = Input(UInt(16.W))
val r_MaxFL = Input(UInt(16.W))
val r_HugEn = Input(Bool())
val StartTxDone = Input(Bool())
val StartTxAbort = Input(Bool())
val RetryCnt = Input(UInt(4.W))
val MTxClk = Input(Bool())
val MaxCollisionOccured = Input(Bool())
val LateCollision = Input(Bool())
val DeferIndication = Input(Bool())
val TxStartFrm = Input(Bool())
val StatePreamble = Input(Bool())
val StateData = Input(UInt(2.W))
val CarrierSense = Input(Bool())
val TxUsedData = Input(Bool())
val Loopback = Input(Bool())
val r_FullD = Input(Bool())
val RstDeferLatched = Input(Bool())
val ReceivedLengthOK = Output(Bool())
val ReceiveEnd = Output(Bool())
val ReceivedPacketGood = Output(Bool())
val InvalidSymbol = Output(Bool())
val LatchedCrcError = Output(Bool())
val RxLateCollision = Output(Bool())
val ShortFrame = Output(Bool())
val DribbleNibble = Output(Bool())
val ReceivedPacketTooBig = Output(Bool())
val LoadRxStatus = Output(Bool())
val RetryCntLatched = Output(UInt(4.W))
val RetryLimit = Output(Bool())
val LateCollLatched = Output(Bool())
val DeferLatched = Output(Bool())
val CarrierSenseLost = Output(Bool())
val LatchedMRxErr = Output(Bool())
}
class MacStatus extends RawModule{
val io: MacStatusIO = IO(new MacStatusIO)
withClockAndReset( io.MRxClk.asClock, io.asyncReset ) {
val LatchedCrcError = RegInit(false.B); io.LatchedCrcError := LatchedCrcError // Crc error
when(io.RxStateSFD){
LatchedCrcError := false.B
} .elsewhen(io.RxStateData.extract(0)){
LatchedCrcError := io.RxCrcError & ~io.RxByteCntEq0;
}
val LatchedMRxErr = RegInit(false.B); io.LatchedMRxErr := LatchedMRxErr // LatchedMRxErr
when(io.MRxErr & io.MRxDV & (io.RxStatePreamble | io.RxStateSFD | io.RxStateData.orR | io.RxStateIdle & ~io.Transmitting)){
LatchedMRxErr := true.B
} .otherwise{
LatchedMRxErr := false.B
}
io.ReceivedPacketGood := ~LatchedCrcError // ReceivedPacketGood
io.ReceivedLengthOK := io.RxByteCnt >= io.r_MinFL & io.RxByteCnt <= io.r_MaxFL // ReceivedLengthOK
// Time to take a sample
val TakeSample =
(io.RxStateData.orR & ~io.MRxDV) |
(io.RxStateData.extract(0) & io.MRxDV & io.RxByteCntMaxFrame)
val LoadRxStatus = RegNext(TakeSample, false.B); io.LoadRxStatus := LoadRxStatus // LoadRxStatus
val ReceiveEnd = RegNext(LoadRxStatus, false.B); io.ReceiveEnd := ReceiveEnd // ReceiveEnd
val SetInvalidSymbol = io.MRxDV & io.MRxErr & io.MRxD === "he".U // Invalid symbol was received during reception in 100Mbps
val InvalidSymbol = RegInit(false.B); io.InvalidSymbol := InvalidSymbol // InvalidSymbol
when(LoadRxStatus & ~SetInvalidSymbol){
InvalidSymbol := false.B
} .elsewhen(SetInvalidSymbol){
InvalidSymbol := true.B
}
val RxLateCollision = RegInit(false.B); io.RxLateCollision := RxLateCollision // Late Collision
val RxColWindow = RegInit(true.B)// Collision Window
when(LoadRxStatus){
RxLateCollision := false.B
} .elsewhen(io.Collision & (~io.r_FullD) & (~RxColWindow | io.r_RecSmall)){
RxLateCollision := true.B
}
when(~io.Collision & io.RxByteCnt(5,0) === io.CollValid & io.RxStateData.extract(1)){
RxColWindow := false.B
} .elsewhen(io.RxStateIdle){
RxColWindow := true.B
}
val ShortFrame = RegInit(false.B); io.ShortFrame := ShortFrame //ShortFrame
when(LoadRxStatus){
ShortFrame := false.B
} .elsewhen(TakeSample){
ShortFrame := io.RxByteCnt < io.r_MinFL
}
// DribbleNibble
val DribbleNibble = RegInit(false.B); io.DribbleNibble := DribbleNibble
when(io.RxStateSFD){
DribbleNibble := false.B
} .elsewhen(~io.MRxDV & io.RxStateData.extract(1)){
DribbleNibble := true.B
}
val ReceivedPacketTooBig = RegInit(false.B); io.ReceivedPacketTooBig := ReceivedPacketTooBig
when(LoadRxStatus){
ReceivedPacketTooBig := false.B
} .elsewhen(TakeSample){
ReceivedPacketTooBig := ~io.r_HugEn & io.RxByteCnt > io.r_MaxFL
}
}
withClockAndReset( io.MTxClk.asClock, io.asyncReset ) {
val RetryCntLatched = RegEnable( io.RetryCnt, 0.U(4.W), io.StartTxDone | io.StartTxAbort); io.RetryCntLatched := RetryCntLatched
val RetryLimit = RegEnable( io.MaxCollisionOccured, false.B, io.StartTxDone | io.StartTxAbort ); io.RetryLimit := RetryLimit // Latched Retransmission limit
val LateCollLatched = RegEnable( io.LateCollision, false.B, io.StartTxDone | io.StartTxAbort); io.LateCollLatched := LateCollLatched // Latched Late Collision
val DeferLatched = RegInit(false.B); io.DeferLatched := DeferLatched // Latched Defer state
when(io.DeferIndication){
DeferLatched := true.B
} .elsewhen(io.RstDeferLatched){
DeferLatched := false.B
}
val CarrierSenseLost = RegInit(false.B); io.CarrierSenseLost := CarrierSenseLost // CarrierSenseLost
when((io.StatePreamble | io.StateData.orR) & ~io.CarrierSense & ~io.Loopback & ~io.Collision & ~io.r_FullD){
CarrierSenseLost := true.B
} .elsewhen(io.TxStartFrm){
CarrierSenseLost := false.B
}
}
}

View File

@@ -0,0 +1,156 @@
package MAC
import chisel3._
import chisel3.util._
class MacTileLinkRxIO extends Bundle{
val RxDataLatched2 = Output(UInt(32.W))
val WriteRxDataToFifo = Output(Bool())
val RxAbortLatched = Output(Bool())
val LatchedRxLength = Output(UInt(16.W))
val RxStatusInLatched = Output( UInt(9.W) )
val ShiftEnded_rck = Output(Bool())
val RxLength = Input(UInt(16.W))
val LoadRxStatus = Input(Bool())
val RxStatusIn = Input(UInt(9.W))
val ShiftEndedSyncb = Input(Bool())
val RxAbortSyncb = Input(Bool())
val WriteRxDataToFifoSyncb = Input(Bool())
val Busy_IRQ_rck = Output(Bool())
val Busy_IRQ_syncb = Input(Bool())
val RxData = Input(UInt(8.W)) // Received data byte (from PHY)
val RxAbort = Input(Bool())
val RxValid = Input(Bool())
val RxReady = Input(Bool())
val RxStartFrm = Input(Bool())
val RxEndFrm = Input(Bool())
}
class MacTileLinkRx extends Module with RequireAsyncReset{
val io = IO(new MacTileLinkRxIO)
val RxDataLatched2 = RegInit(0.U(32.W)); io.RxDataLatched2 := RxDataLatched2
val RxDataLatched1 = RegInit(0.U(24.W)) // Little Endian Byte Ordering[23:0]
val RxValidBytes = RegInit(1.U(2.W))
val RxByteCnt = RegInit(0.U(2.W))
val LastByteIn = RegInit(false.B)
val ShiftWillEnd = RegInit(false.B)
val WriteRxDataToFifo = RegInit(false.B); io.WriteRxDataToFifo := WriteRxDataToFifo
val RxAbortLatched = RegInit(false.B); io.RxAbortLatched := RxAbortLatched
val LatchedRxLength = RegEnable(io.RxLength, 0.U(16.W), io.LoadRxStatus); io.LatchedRxLength := LatchedRxLength
val RxStatusInLatched = RegEnable(io.RxStatusIn, 0.U(9.W), io.LoadRxStatus); io.RxStatusInLatched := RxStatusInLatched
val ShiftEnded_rck = RegInit(false.B); io.ShiftEnded_rck := ShiftEnded_rck
val RxEnableWindow = RegInit(false.B)
val Busy_IRQ_rck = RegInit(false.B); io.Busy_IRQ_rck := Busy_IRQ_rck
// Indicating that last byte is being reveived
when(ShiftWillEnd & RxByteCnt.andR | io.RxAbort){
LastByteIn := false.B
} .elsewhen(io.RxValid & io.RxReady & io.RxEndFrm & ~(RxByteCnt.andR) & RxEnableWindow){
LastByteIn := true.B
}
// Indicating that data reception will end
val StartShiftWillEnd = LastByteIn | io.RxValid & io.RxEndFrm & RxByteCnt.andR & RxEnableWindow
when(ShiftEnded_rck | io.RxAbort){
ShiftWillEnd := false.B
} .elsewhen(StartShiftWillEnd){
ShiftWillEnd := true.B
}
// Receive byte counter
when(ShiftEnded_rck | io.RxAbort){
RxByteCnt := 0.U
} .elsewhen(io.RxValid & io.RxStartFrm & io.RxReady){
RxByteCnt := 1.U
} .elsewhen(io.RxValid & RxEnableWindow & io.RxReady | LastByteIn){
RxByteCnt := RxByteCnt + 1.U
}
// Indicates how many bytes are valid within the last word
when(io.RxValid & io.RxStartFrm){
RxValidBytes := 1.U
} .elsewhen(io.RxValid & ~LastByteIn & ~io.RxStartFrm & RxEnableWindow){
RxValidBytes := RxValidBytes + 1.U
}
when(io.RxValid & io.RxReady & ~LastByteIn){
when(io.RxStartFrm){
RxDataLatched1 := Cat(RxDataLatched1(23, 8), io.RxData)// Little Endian Byte Ordering
} .elsewhen(RxEnableWindow){
RxDataLatched1 := Mux1H(Seq(
( RxByteCnt === 0.U ) -> Cat(RxDataLatched1(23, 8), io.RxData),// Little Endian Byte Ordering
( RxByteCnt === 1.U ) -> Cat(RxDataLatched1(23,16), io.RxData, RxDataLatched1( 7,0)),
( RxByteCnt === 2.U ) -> Cat( io.RxData, RxDataLatched1(15,0)),
( RxByteCnt === 3.U ) -> RxDataLatched1,
))
}
}
// Indicating start of the reception process
val SetWriteRxDataToFifo =
(io.RxValid & io.RxReady & ~io.RxStartFrm & RxEnableWindow & (RxByteCnt.andR)) |
(ShiftWillEnd & LastByteIn & (RxByteCnt.andR))
// Assembling data that will be written to the rx_fifo
when(SetWriteRxDataToFifo & ~ShiftWillEnd){
RxDataLatched2 := Cat(io.RxData, RxDataLatched1)// Little Endian Byte Ordering
} .elsewhen(SetWriteRxDataToFifo & ShiftWillEnd){
RxDataLatched2 := Mux1H(Seq( // Little Endian Byte Ordering
( RxValidBytes === 0.U ) -> Cat(io.RxData, RxDataLatched1),
( RxValidBytes === 1.U ) -> Cat(0.U(24.W), RxDataLatched1(7,0) ),
( RxValidBytes === 2.U ) -> Cat(0.U(16.W), RxDataLatched1(15, 0) ),
( RxValidBytes === 3.U ) -> Cat(0.U(8.W), RxDataLatched1 ),
))
}
when(SetWriteRxDataToFifo & ~io.RxAbort){
WriteRxDataToFifo := true.B
} .elsewhen(io.WriteRxDataToFifoSyncb | io.RxAbort){
WriteRxDataToFifo := false.B
}
// Generation of the end-of-frame signal
when(~io.RxAbort & SetWriteRxDataToFifo & StartShiftWillEnd){
ShiftEnded_rck := true.B
} .elsewhen(io.RxAbort | io.ShiftEndedSyncb & RegNext(io.ShiftEndedSyncb, false.B) ){
ShiftEnded_rck := false.B
}
// Generation of the end-of-frame signal
when(io.RxStartFrm){
RxEnableWindow := true.B
} .elsewhen(io.RxEndFrm | io.RxAbort){
RxEnableWindow := false.B
}
when(io.RxAbortSyncb){
RxAbortLatched := false.B
} .elsewhen(io.RxAbort){
RxAbortLatched := true.B
}
when(io.RxValid & io.RxStartFrm & ~io.RxReady){
Busy_IRQ_rck := true.B
} .elsewhen(io.Busy_IRQ_syncb){
Busy_IRQ_rck := false.B
}
}

View File

@@ -0,0 +1,123 @@
package MAC
import chisel3._
import chisel3.util._
class MacTileLinkTxIO extends Bundle{
val RstDeferLatched = Output(Bool())
val BlockingTxStatusWrite_sync = Input(Bool())
val TxStartFrm_sync = Input(Bool())
val TxStartFrm = Output(Bool()) // Transmit packet start frame
val TxEndFrm = Output(Bool()) // Transmit packet end frame
val TxData = Output(UInt(8.W)) // Transmit packet data byte
val TxUsedData = Input(Bool()) // Transmit packet used data
val TxRetry = Input(Bool()) // Transmit packet retry
val TxAbort = Input(Bool()) // Transmit packet abort
val TxDone = Input(Bool()) // Transmission ended
val ReadTxDataFromFifo_tck = Output(Bool())
val ReadTxDataFromFifo_syncb = Input(Bool())
val TxEndFrm_wb = Input(Bool())
val TxValidBytesLatched = Input(UInt(2.W))
val TxData_wb = Input(UInt(32.W))
}
class MacTileLinkTx extends Module with RequireAsyncReset{
val io = IO(new MacTileLinkTxIO)
io.RstDeferLatched := io.BlockingTxStatusWrite_sync & ~RegNext(io.BlockingTxStatusWrite_sync, false.B)
val TxStartFrm = RegInit(false.B); io.TxStartFrm := TxStartFrm
val TxEndFrm = RegInit(false.B); io.TxEndFrm := TxEndFrm
val TxData = RegInit(0.U(8.W)); io.TxData := TxData
val TxDataLatched = RegInit(0.U(32.W))
val TxByteCnt = RegInit(0.U(2.W))
val LastWord = RegInit(false.B)
val ReadTxDataFromFifo_tck = RegInit(false.B); io.ReadTxDataFromFifo_tck := ReadTxDataFromFifo_tck
// Generating delayed signals
val TxAbort_q = RegNext( io.TxAbort, false.B)
val TxRetry_q = RegNext( io.TxRetry, false.B)
val TxUsedData_q = RegNext( io.TxUsedData, false.B)
// Changes for tx occur every second clock. Flop is used for this manner.
val Flop = RegInit(false.B)
when( io.TxDone | io.TxAbort | TxRetry_q){
Flop := false.B
} .elsewhen ( io.TxUsedData ){
Flop := ~Flop
}
when(io.TxStartFrm_sync){
TxStartFrm := true.B
} .elsewhen(TxUsedData_q | ~io.TxStartFrm_sync & (io.TxRetry & (~TxRetry_q) | io.TxAbort & (~TxAbort_q))){
TxStartFrm := false.B
}
// Indication of the last word
when( (TxEndFrm | io.TxAbort | io.TxRetry) & Flop ){
LastWord := false.B
} .elsewhen( io.TxUsedData & Flop & TxByteCnt === 3.U ){
LastWord := io.TxEndFrm_wb
}
// Tx end frame generation
when(Flop & TxEndFrm | io.TxAbort | TxRetry_q){
TxEndFrm := false.B
} .elsewhen(Flop & LastWord){
TxEndFrm :=
Mux1H(Seq(
(io.TxValidBytesLatched === 1.U) -> (TxByteCnt === 0.U),
(io.TxValidBytesLatched === 2.U) -> (TxByteCnt === 1.U),
(io.TxValidBytesLatched === 3.U) -> (TxByteCnt === 2.U),
(io.TxValidBytesLatched === 0.U) -> (TxByteCnt === 3.U),
))
}
// Tx data selection (latching)
when( io.TxStartFrm_sync & ~TxStartFrm ){
TxData := io.TxData_wb( 7, 0) // little Endian Byte Ordering
} .elsewhen(io.TxUsedData & Flop){
TxData := Mux1H(Seq(
(TxByteCnt === 0.U) -> TxDataLatched( 7, 0),// little Endian Byte Ordering
(TxByteCnt === 1.U) -> TxDataLatched(15, 8),
(TxByteCnt === 2.U) -> TxDataLatched(23,16),
(TxByteCnt === 3.U) -> TxDataLatched(31,24),
))
}
// Latching tx data
when(
io.TxStartFrm_sync & ~TxStartFrm |
io.TxUsedData & Flop & TxByteCnt === 3.U |
TxStartFrm & io.TxUsedData & Flop & TxByteCnt === 0.U){
TxDataLatched := io.TxData_wb
}
// Tx Byte counter
when(TxAbort_q | TxRetry_q){
TxByteCnt := 0.U
} .elsewhen(TxStartFrm & ~io.TxUsedData){
TxByteCnt := 1.U
} .elsewhen(io.TxUsedData & Flop){
TxByteCnt := TxByteCnt + 1.U
}
when(io.TxStartFrm_sync & ~TxStartFrm | io.TxUsedData & Flop & TxByteCnt === 3.U &
~LastWord | TxStartFrm & io.TxUsedData & Flop & TxByteCnt === 0.U ){
ReadTxDataFromFifo_tck := true.B
} .elsewhen(io.ReadTxDataFromFifo_syncb & ~RegNext(io.ReadTxDataFromFifo_syncb, false.B)){
ReadTxDataFromFifo_tck := false.B
}
}

View File

@@ -0,0 +1,288 @@
package MAC
import chisel3._
import chisel3.util._
import Switch._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy._
import org.chipsalliance.cde.config._
abstract class MacTileLinkBase() extends Module{
class MacTileLinkIO extends Bundle{
val r_RxEn = Input(Bool()) // Receive enable
val RxDataLatched2_rxclk = Input(UInt(32.W))
val WriteRxDataToFifoSync = Input(Bool())
val RxAbortSync = Input(Bool())
val LatchedRxLength_rxclk = Input(UInt(16.W))
val RxStatusInLatched_rxclk = Input(UInt(9.W))
val ShiftEndedSync = Input(Bool())
val RxReady = Output(Bool())
val TxStartFrm_wb = Output(Bool())
val TxStartFrm_syncb = Input(Bool())
val TxEndFrm_wb = Output(Bool())
val TxData_wb = Output(UInt(32.W))
val ReadTxDataFromFifo_sync = Input(Bool())
// Tx Status signals
val RetryCntLatched = Input(UInt(4.W)) // Latched Retry Counter
val RetryLimit = Input(Bool()) // Retry limit reached (Retry Max value +1 attempts were made)
val LateCollLatched = Input(Bool()) // Late collision occured
val DeferLatched = Input(Bool()) // Defer indication (Frame was defered before sucessfully sent)
val CarrierSenseLost = Input(Bool()) // Carrier Sense was lost during the frame transmission
val PerPacketCrcEn = Output(Bool()) // Per packet crc enable
val PerPacketPad = Output(Bool()) // Per packet pading
//Register
val r_TxEn = Input(Bool()) // Transmit enable
val BlockingTxStatusWrite = Output(Bool())
val TxUsedData = Input(Bool()) // Transmit packet used data
val TxValidBytesLatched = Output(UInt(2.W))
val TxRetrySync = Input(Bool())
val TxAbortSync = Input(Bool()) // Transmit packet abort
val TxDoneSync = Input(Bool()) // Transmission ended
val rxEnq = new Receive_Enq_Bundle
val txDeq = Flipped(new Transmit_Deq_Bundle)
}
val io = IO(new MacTileLinkIO)
val ShiftEndedSyncPluse = io.ShiftEndedSync & ~RegNext(io.ShiftEndedSync, false.B)
val RxAbortPluse = io.RxAbortSync & ~RegNext(io.RxAbortSync, false.B)
val WriteRxDataToFifoSyncPluse = io.WriteRxDataToFifoSync & ~RegNext(io.WriteRxDataToFifoSync, false.B)
val RxReady = RegInit(false.B); io.RxReady := RxReady
val rxBuffCtrlValid = RegInit(false.B)
io.rxEnq.ctrl.valid := rxBuffCtrlValid
io.rxEnq.ctrl.bits.LatchedRxLength := RegEnable(io.LatchedRxLength_rxclk, ShiftEndedSyncPluse | RxAbortPluse)
io.rxEnq.ctrl.bits.RxStatusInLatched := RegEnable(io.RxStatusInLatched_rxclk, ShiftEndedSyncPluse | RxAbortPluse)
io.rxEnq.ctrl.bits.isRxAbort := RegEnable(RxAbortPluse, false.B, ShiftEndedSyncPluse | RxAbortPluse)
when( io.rxEnq.ctrl.fire ){
rxBuffCtrlValid := false.B
} .elsewhen( ShiftEndedSyncPluse | RxAbortPluse ){
rxBuffCtrlValid := true.B
}
// RxReady generation
when(ShiftEndedSyncPluse | RxAbortPluse ){
RxReady := false.B
} .elsewhen( io.r_RxEn & (io.rxEnq.data.ready) ){
RxReady := true.B
}
io.rxEnq.data.bits := io.RxDataLatched2_rxclk
io.rxEnq.data.valid := WriteRxDataToFifoSyncPluse
assert( ~(io.rxEnq.data.valid & ~io.rxEnq.data.ready), "Assert Failed, rx overrun!" )
val TxStartFrm_wb = RegInit(false.B); io.TxStartFrm_wb := TxStartFrm_wb
val TxEndFrm_wb = RegInit(false.B); io.TxEndFrm_wb := TxEndFrm_wb
val TxLength = RegInit(0.U(16.W))
val LatchedTxLength = RegInit(0.U(16.W))
val txRetryPulse = io.TxRetrySync & ~RegNext(io.TxRetrySync, false.B)
val txDonePulse = io.TxDoneSync & ~RegNext(io.TxDoneSync, false.B)
val txAbortPulse = io.TxAbortSync & ~RegNext(io.TxAbortSync, false.B)
val ReadTxDataFromFifoSyncPluse = io.ReadTxDataFromFifo_sync & ~RegNext(io.ReadTxDataFromFifo_sync, false.B)
io.PerPacketPad := RegEnable(io.txDeq.req.bits.PerPacketPad, false.B, io.txDeq.req.fire)
io.PerPacketCrcEn := RegEnable(io.txDeq.req.bits.PerPacketCrcEn, false.B, io.txDeq.req.fire)
when( io.txDeq.req.fire ){
TxStartFrm_wb := true.B
} .elsewhen(io.TxStartFrm_syncb){
TxStartFrm_wb := false.B
}
when((TxLength === 0.U) & io.TxUsedData){
TxEndFrm_wb := true.B
} .elsewhen(txRetryPulse | txDonePulse | txAbortPulse){
TxEndFrm_wb := false.B
}
when( io.txDeq.req.fire ){
TxLength := io.txDeq.req.bits.txLength
LatchedTxLength := io.txDeq.req.bits.txLength
} .elsewhen( io.txDeq.data.fire ){
when( TxLength < 4.U ){
TxLength := 0.U
} .otherwise{
TxLength := TxLength - 4.U // Length is subtracted at the data request
}
}
val txRespValid = RegInit(false.B)
val txRespBits = Reg(new Transmit_Deq_Resp_Bundle)
io.txDeq.resp.valid := txRespValid
io.txDeq.resp.bits := txRespBits
when( io.txDeq.resp.fire ){
txRespValid := false.B
} .elsewhen( txRetryPulse | txDonePulse | txAbortPulse ){
txRespValid := true.B
txRespBits.RetryCntLatched := io.RetryCntLatched
txRespBits.RetryLimit := io.RetryLimit
txRespBits.LateCollLatched := io.LateCollLatched
txRespBits.DeferLatched := io.DeferLatched
txRespBits.CarrierSenseLost := io.CarrierSenseLost
txRespBits.isClear := txAbortPulse | txRetryPulse
}
val isTxBusy = RegInit(false.B); io.txDeq.req.ready := ~isTxBusy & io.r_TxEn
when( io.txDeq.req.fire){
isTxBusy := true.B
} .elsewhen(txRetryPulse | txDonePulse | txAbortPulse){
isTxBusy := false.B
}
io.txDeq.data.ready := ReadTxDataFromFifoSyncPluse
assert( ~(io.txDeq.data.ready & ~io.txDeq.data.valid), "Assert Failed, Tx should never under run!" )
io.TxData_wb := io.txDeq.data.bits
val BlockingTxStatusWrite = RegInit(false.B); io.BlockingTxStatusWrite := BlockingTxStatusWrite
when(~io.TxDoneSync & ~io.TxAbortSync){
BlockingTxStatusWrite := false.B
} .elsewhen(txDonePulse | txAbortPulse){
BlockingTxStatusWrite := true.B
}
// Marks which bytes are valid within the word.
val TxValidBytesLatched = RegInit(0.U(2.W)); io.TxValidBytesLatched := TxValidBytesLatched
val LatchValidBytes = ShiftRegisters((TxLength < 4.U), 2, false.B, true.B)
val LatchValidBytesPluse = LatchValidBytes(0) & ~LatchValidBytes(1)
// Latching valid bytes
when(LatchValidBytesPluse){
TxValidBytesLatched := Mux(TxLength < 4.U, TxLength(1,0), 0.U)
} .elsewhen(txRetryPulse | txDonePulse | txAbortPulse){
TxValidBytesLatched := 0.U
}
}
class MacTileLink() extends MacTileLinkBase(){
}

View File

@@ -0,0 +1,108 @@
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

@@ -0,0 +1,61 @@
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
}