拓扑修改,编译通过
This commit is contained in:
471
src/main/scala/Switch/MacRegisters.scala
Normal file
471
src/main/scala/Switch/MacRegisters.scala
Normal file
@@ -0,0 +1,471 @@
|
||||
package MAC
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
import freechips.rocketchip.regmapper._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import org.chipsalliance.cde.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.interrupts._
|
||||
|
||||
class Mac_Config_Bundle extends Bundle{
|
||||
val WCtrlDataStart = Input(Bool())
|
||||
val RStatStart = Input(Bool())
|
||||
val UpdateMIIRX_DATAReg = Input(Bool())
|
||||
val Prsd = Input(UInt(16.W))
|
||||
val NValid_stat = Input(Bool())
|
||||
val Busy_stat = Input(Bool())
|
||||
val LinkFail = Input(Bool())
|
||||
val TxB_IRQ = Input(Bool())
|
||||
val TxE_IRQ = Input(Bool())
|
||||
val RxB_IRQ = Input(Bool())
|
||||
val RxE_IRQ = Input(Bool())
|
||||
val Busy_IRQ = Input(Bool())
|
||||
val RstTxPauseRq = Input(Bool())
|
||||
val TxCtrlEndFrm = Input(Bool())
|
||||
val StartTxDone = Input(Bool())
|
||||
val TxClk = Input(Bool())
|
||||
val RxClk = Input(Bool())
|
||||
val SetPauseTimer = Input(Bool())
|
||||
|
||||
val r_RecSmall = Output(Bool())
|
||||
val r_Pad = Output(Bool())
|
||||
val r_HugEn = Output(Bool())
|
||||
val r_CrcEn = Output(Bool())
|
||||
val r_DlyCrcEn = Output(Bool())
|
||||
val r_FullD = Output(Bool())
|
||||
val r_ExDfrEn = Output(Bool())
|
||||
val r_NoBckof = Output(Bool())
|
||||
val r_LoopBck = Output(Bool())
|
||||
val r_IFG = Output(Bool())
|
||||
val r_Pro = Output(Bool())
|
||||
val r_Iam = Output(Bool())
|
||||
val r_Bro = Output(Bool())
|
||||
val r_NoPre = Output(Bool())
|
||||
val r_TxEn = Output(Bool())
|
||||
val r_RxEn = Output(Bool())
|
||||
val r_HASH0 = Output(UInt(32.W))
|
||||
val r_HASH1 = Output(UInt(32.W))
|
||||
val r_IPGT = Output(UInt(7.W))
|
||||
val r_IPGR1 = Output(UInt(7.W))
|
||||
val r_IPGR2 = Output(UInt(7.W))
|
||||
val r_MinFL = Output(UInt(16.W))
|
||||
val r_MaxFL = Output(UInt(16.W))
|
||||
val r_MaxRet = Output(UInt(4.W))
|
||||
val r_CollValid = Output(UInt(6.W))
|
||||
val r_TxFlow = Output(Bool())
|
||||
val r_RxFlow = Output(Bool())
|
||||
val r_PassAll = Output(Bool())
|
||||
val r_MiiNoPre = Output(Bool())
|
||||
val r_ClkDiv = Output(UInt(8.W))
|
||||
val r_WCtrlData = Output(Bool())
|
||||
val r_RStat = Output(Bool())
|
||||
val r_ScanStat = Output(Bool())
|
||||
val r_RGAD = Output(UInt(5.W))
|
||||
val r_FIAD = Output(UInt(5.W))
|
||||
val r_CtrlData = Output(UInt(16.W))
|
||||
val r_MAC = Output(UInt(48.W))
|
||||
val r_TxBDNum = Output(UInt(8.W))
|
||||
val r_TxPauseTV = Output(UInt(16.W))
|
||||
val r_TxPauseRq = Output(Bool())
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class MacRegIO extends Mac_Config_Bundle{
|
||||
val asyncReset = Input(AsyncReset())
|
||||
}
|
||||
|
||||
class MacReg(implicit p: Parameters) extends LazyModule{
|
||||
|
||||
// DTS
|
||||
val dtsdevice = new SimpleDevice("mac",Seq("mac_0"))
|
||||
val int_node = IntSourceNode(IntSourcePortSimple(num = 1, resources = dtsdevice.int))
|
||||
|
||||
|
||||
val configNode = TLRegisterNode(
|
||||
address = Seq(AddressSet(0x30000000L, 0x000003ffL)),
|
||||
device = dtsdevice,
|
||||
concurrency = 1,
|
||||
beatBytes = 32/8,
|
||||
executable = true
|
||||
)
|
||||
lazy val module = new MacRegImp(this)
|
||||
}
|
||||
|
||||
class MacRegImp(outer: MacReg)(implicit p: Parameters) extends LazyModuleImp(outer){
|
||||
|
||||
val io: MacRegIO = IO(new MacRegIO)
|
||||
val (int, _) = outer.int_node.out(0)
|
||||
|
||||
|
||||
val RecSmall = RegInit(false.B)
|
||||
val Pad = RegInit(true.B)
|
||||
val HugEn = RegInit(false.B)
|
||||
val CrcEn = RegInit(true.B)
|
||||
val DlyCrcEn = RegInit(false.B)
|
||||
|
||||
val FullD = RegInit(false.B)
|
||||
val ExDfrEn = RegInit(false.B)
|
||||
val NoBckof = RegInit(false.B)
|
||||
val LoopBck = RegInit(false.B)
|
||||
val IFG = RegInit(false.B)
|
||||
val Pro = RegInit(false.B)
|
||||
val Iam = RegInit(false.B)
|
||||
val Bro = RegInit(false.B)
|
||||
val NoPre = RegInit(false.B)
|
||||
val TxEn = RegInit(false.B)
|
||||
val RxEn = RegInit(false.B)
|
||||
|
||||
// Interrupt generation
|
||||
val irq_txb = RegInit(false.B)
|
||||
val irq_txe = RegInit(false.B)
|
||||
val irq_rxb = RegInit(false.B)
|
||||
val irq_rxe = RegInit(false.B)
|
||||
val irq_busy = RegInit(false.B)
|
||||
val irq_txc = RegInit(false.B)
|
||||
val irq_rxc = RegInit(false.B)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
val INT_MASK = RegInit(0.U(7.W)) // INT_MASK Register
|
||||
val IPGT = RegInit("h12".U(7.W)) // IPGT Register
|
||||
val IPGR1 = RegInit("h0C".U(7.W)) // IPGR1 Register
|
||||
val IPGR2 = RegInit("h12".U(7.W))
|
||||
|
||||
val maxFL = RegInit("h0600".U(16.W))
|
||||
val minFL = RegInit("h0040".U(16.W))
|
||||
|
||||
val collValid = RegInit("h3f".U(6.W))
|
||||
val maxRet = RegInit("hF".U(4.W))
|
||||
|
||||
val TX_BD_NUM = RegInit("h40".U(8.W)) // TX_BD_NUM Register
|
||||
|
||||
val txFlow = RegInit(false.B)
|
||||
val rxFlow = RegInit(false.B)
|
||||
val passAll = RegInit(false.B)
|
||||
|
||||
val clkDiv = RegInit("h64".U(8.W))
|
||||
val miiNoPre = RegInit(false.B)
|
||||
|
||||
|
||||
val scanStat = RegInit(false.B)
|
||||
val readStat = RegInit(false.B)
|
||||
val wCtrlData = RegInit(false.B)
|
||||
|
||||
when(io.RStatStart){ readStat := false.B }
|
||||
when(io.WCtrlDataStart){ wCtrlData := false.B }
|
||||
|
||||
val FIAD = RegInit(0.U(5.W))
|
||||
val RGAD = RegInit(0.U(5.W))
|
||||
|
||||
val MIITX_DATA = RegInit(0.U(16.W)) // MIITX_DATA Register
|
||||
|
||||
val MIIRX_DATA = RegEnable(io.Prsd, 0.U(16.W), io.UpdateMIIRX_DATAReg) // MIIRX_DATA Register
|
||||
|
||||
val Mac_ADDR0 = RegInit(0.U(32.W))
|
||||
val Mac_ADDR1 = RegInit(0.U(16.W))
|
||||
|
||||
val HASH0 = RegInit(0.U(32.W))
|
||||
val HASH1 = RegInit(0.U(32.W))
|
||||
|
||||
val txPauseRq = RegInit(false.B)
|
||||
val txPauseTV = RegInit(0.U(16.W))
|
||||
|
||||
when( io.RstTxPauseRq ){ txPauseRq := false.B }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
outer.configNode.regmap(
|
||||
( 0 << 2 ) ->
|
||||
RegFieldGroup("MODER", Some("Mode Register"), Seq(
|
||||
RegField(1, RxEn , RegFieldDesc( "RxEn", "RxEn", reset = Some(0))) ,
|
||||
RegField(1, TxEn , RegFieldDesc( "TxEn", "TxEn", reset = Some(0) ) ),
|
||||
RegField(1, NoPre , RegFieldDesc( "NoPre", "NoPre", reset = Some(0) ) ),
|
||||
RegField(1, Bro , RegFieldDesc( "Bro", "Bro", reset = Some(0) ) ),
|
||||
RegField(1, Iam , RegFieldDesc( "Iam", "Iam", reset = Some(0) ) ),
|
||||
RegField(1, Pro , RegFieldDesc( "Pro", "Pro", reset = Some(0) ) ),
|
||||
RegField(1, IFG , RegFieldDesc( "IFG", "IFG", reset = Some(0) ) ),
|
||||
RegField(1, LoopBck, RegFieldDesc( "LoopBck", "LoopBck", reset = Some(0) ) ),
|
||||
RegField(1, NoBckof, RegFieldDesc( "NoBckof", "NoBckof", reset = Some(0) ) ),
|
||||
RegField(1, ExDfrEn, RegFieldDesc( "ExDfrEn", "ExDfrEn", reset = Some(0) ) ),
|
||||
RegField(1, FullD , RegFieldDesc( "FullD", "FullD", reset = Some(0) ) ),
|
||||
RegField.r(1, 0.U),
|
||||
RegField(1, DlyCrcEn, RegFieldDesc( "DlyCrcEn", "DlyCrcEn", reset=Some(0)) ),
|
||||
RegField(1, CrcEn , RegFieldDesc( "CrcEn", "CrcEn", reset=Some(1)) ),
|
||||
RegField(1, HugEn , RegFieldDesc( "HugEn", "HugEn", reset=Some(0)) ),
|
||||
RegField(1, Pad , RegFieldDesc( "Pad", "Pad", reset=Some(1)) ),
|
||||
RegField(1, RecSmall, RegFieldDesc( "RecSmall", "RecSmall", reset=Some(0)) )
|
||||
)),
|
||||
|
||||
( 1 << 2 ) ->
|
||||
RegFieldGroup("INT_SOURCE", Some("Interrupt Source Register"), Seq(
|
||||
RegField(1, irq_txb, RegWriteFn((valid, data) => { when ((valid & data) === 1.U) { irq_txb := 0.U }; true.B }), RegFieldDesc("txb", "txb", reset=Some(0))),
|
||||
RegField(1, irq_txe, RegWriteFn((valid, data) => { when ((valid & data) === 1.U) { irq_txe := 0.U }; true.B }), RegFieldDesc("txe", "txe", reset=Some(0))),
|
||||
RegField(1, irq_rxb, RegWriteFn((valid, data) => { when ((valid & data) === 1.U) { irq_rxb := 0.U }; true.B }), RegFieldDesc("rxb", "rxb", reset=Some(0))),
|
||||
RegField(1, irq_rxe, RegWriteFn((valid, data) => { when ((valid & data) === 1.U) { irq_rxe := 0.U }; true.B }), RegFieldDesc("rxe", "rxe", reset=Some(0))),
|
||||
RegField(1, irq_busy, RegWriteFn((valid, data) => { when ((valid & data) === 1.U) { irq_busy := 0.U }; true.B }), RegFieldDesc("busy", "busy", reset=Some(0))),
|
||||
RegField(1, irq_txc, RegWriteFn((valid, data) => { when ((valid & data) === 1.U) { irq_txc := 0.U }; true.B }), RegFieldDesc("txc", "txc", reset=Some(0))),
|
||||
RegField(1, irq_rxc, RegWriteFn((valid, data) => { when ((valid & data) === 1.U) { irq_rxc := 0.U }; true.B }), RegFieldDesc("rxc", "rxc", reset=Some(0))),
|
||||
)),
|
||||
|
||||
( 2 << 2 ) ->
|
||||
RegFieldGroup("INT_MASK", Some("Interrupt Mask Register"), Seq(
|
||||
RegField(7, INT_MASK)
|
||||
)),
|
||||
|
||||
( 3 << 2 ) ->
|
||||
RegFieldGroup("IPGT", Some("Back to Back Inter Packet Gap Register"), Seq(
|
||||
RegField(7, IPGT, RegFieldDesc("IPGT", "IPGT", reset=Some(0x12)))
|
||||
)),
|
||||
|
||||
( 4 << 2 ) ->
|
||||
RegFieldGroup("IPGR1", Some("Non Back to Back Inter Packet Gap Register 1"), Seq(
|
||||
RegField(7, IPGR1, RegFieldDesc("IPGR1", "IPGR1", reset=Some(0xc)))
|
||||
)),
|
||||
|
||||
( 5 << 2 ) ->
|
||||
RegFieldGroup("IPGR2", Some("Non Back to Back Inter Packet Gap Register 2"), Seq(
|
||||
RegField(7, IPGR2, RegFieldDesc("IPGR2", "IPGR2", reset=Some(0x12)))
|
||||
)),
|
||||
|
||||
( 6 << 2 ) ->
|
||||
RegFieldGroup("PACKETLEN", Some("Packet Length Register"),
|
||||
RegField.bytes(maxFL, Some(RegFieldDesc("maxFL", "Maximum Frame Length", reset=Some(0x0600)))) ++
|
||||
RegField.bytes(minFL, Some(RegFieldDesc("minFL", "Minimum Frame Length", reset=Some(0x0040))))
|
||||
),
|
||||
( 7 << 2 ) ->
|
||||
RegFieldGroup("COLLCONF", Some("Collision and Retry Configuration Register"), Seq(
|
||||
RegField(6, collValid, RegFieldDesc("collValid", "Collision Valid", reset=Some(0x3f))),
|
||||
RegField.r(10,0.U),
|
||||
RegField(4, maxRet, RegFieldDesc("maxRet", "Maximum Retry", reset=Some(0xf))),
|
||||
)),
|
||||
( 8 << 2 ) ->
|
||||
RegFieldGroup("TX_BD_NUM", Some("Transmit BD Number Register"), Seq(
|
||||
RegField(8, TX_BD_NUM, RegWriteFn((valid, data) => { when (valid & data <= "h80".U) { TX_BD_NUM := data }; true.B }), RegFieldDesc("TX_BD_NUM", "TX_BD_NUM", reset=Some(0x40))),
|
||||
)),
|
||||
|
||||
( 9 << 2 ) ->
|
||||
RegFieldGroup("CTRLMODER", Some("Control Module Mode Register"), Seq(
|
||||
RegField(1, passAll, RegFieldDesc("PassAll", "Pass All Receive Frames", reset=Some(0))),
|
||||
RegField(1, rxFlow , RegFieldDesc("RxFlow", "Receive Flow Control", reset=Some(0))),
|
||||
RegField(1, txFlow , RegFieldDesc("TxFlow", "Transmit Flow Control", reset=Some(0))),
|
||||
)),
|
||||
|
||||
( 10 << 2 ) ->
|
||||
RegFieldGroup("MIIMODER", Some("MII Mode Register"), Seq(
|
||||
RegField(8, clkDiv, RegFieldDesc("clkDiv", "Clock Divider", reset=Some(0x64))),
|
||||
RegField(1, miiNoPre, RegFieldDesc("MIINoPre", "NO Preamble", reset=Some(0x0))),
|
||||
)),
|
||||
|
||||
( 11 << 2 ) ->
|
||||
RegFieldGroup("MIICOMMAND", Some("MII Command Register"), Seq(
|
||||
RegField(1, scanStat, RegFieldDesc("scanStat", "Scan Status", reset=Some(0x0))),
|
||||
RegField(1, readStat, RegFieldDesc("readStat", "Read Status", reset=Some(0x0))),
|
||||
RegField(1, wCtrlData, RegFieldDesc("wCtrlData", "Write Control Data", reset=Some(0x0))),
|
||||
)),
|
||||
|
||||
( 12 << 2 ) ->
|
||||
RegFieldGroup("MIIADDRESS", Some("MII Address Register"), Seq(
|
||||
RegField(5, FIAD, RegFieldDesc("FIAD", "PHY Address", reset=Some(0x0))),
|
||||
RegField.r(3 ,0.U),
|
||||
RegField(5, RGAD, RegFieldDesc("RGAD", "Register Address", reset=Some(0x0))),
|
||||
)),
|
||||
|
||||
( 13 << 2 ) ->
|
||||
RegFieldGroup("MIITX_DATA", Some("MII Transmit Data"),
|
||||
RegField.bytes(MIITX_DATA)
|
||||
),
|
||||
|
||||
( 14 << 2 ) ->
|
||||
RegFieldGroup("MIIRX_DATA", Some("MII Receive Data"), Seq(
|
||||
RegField.r(16, MIIRX_DATA)
|
||||
)),
|
||||
|
||||
( 15 << 2 ) ->
|
||||
RegFieldGroup("MIISTATUS", Some("MII Status Register"), Seq(
|
||||
RegField.r(1, io.LinkFail),
|
||||
RegField.r(1, io.Busy_stat),
|
||||
RegField.r(1, io.NValid_stat),
|
||||
)),
|
||||
|
||||
( 16 << 2 ) ->
|
||||
RegFieldGroup("MAC_ADDR0", Some("MAC Address Register 0"),
|
||||
RegField.bytes(Mac_ADDR0)
|
||||
),
|
||||
|
||||
( 17 << 2 ) ->
|
||||
RegFieldGroup("MAC_ADDR1", Some("MAC Address Register 1"),
|
||||
RegField.bytes(Mac_ADDR1)
|
||||
),
|
||||
|
||||
( 18 << 2 ) ->
|
||||
RegFieldGroup("HASH0", Some("HASH Register 0"),
|
||||
RegField.bytes(HASH0)
|
||||
),
|
||||
|
||||
( 19 << 2 ) ->
|
||||
RegFieldGroup("HASH1", Some("HASH Register 1"),
|
||||
RegField.bytes(HASH1)
|
||||
),
|
||||
|
||||
( 20 << 2 ) ->
|
||||
RegFieldGroup("TXCTRL", Some("Tx Control Register"),
|
||||
RegField.bytes(txPauseTV, Some(RegFieldDesc("TxPauseTV", "Tx Pause Timer Value", reset=Some(0x0)))) ++ Seq(
|
||||
RegField(1, txPauseRq, RegFieldDesc("TxPauseRQ", "Tx Pause Request", reset=Some(0x0))),
|
||||
)),
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
io.r_RecSmall := RecSmall
|
||||
io.r_Pad := Pad
|
||||
io.r_HugEn := HugEn
|
||||
io.r_CrcEn := CrcEn
|
||||
io.r_DlyCrcEn := DlyCrcEn
|
||||
io.r_FullD := FullD
|
||||
io.r_ExDfrEn := ExDfrEn
|
||||
io.r_NoBckof := NoBckof
|
||||
io.r_LoopBck := LoopBck
|
||||
io.r_IFG := IFG
|
||||
io.r_Pro := Pro
|
||||
io.r_Iam := Iam
|
||||
io.r_Bro := Bro
|
||||
io.r_NoPre := NoPre
|
||||
io.r_TxEn := TxEn & (TX_BD_NUM > 0.U) // Transmission is enabled when there is at least one TxBD.
|
||||
io.r_RxEn := RxEn & (TX_BD_NUM < "h80".U) // Reception is enabled when there is at least one RxBD.
|
||||
|
||||
io.r_IPGT := IPGT
|
||||
io.r_IPGR1 := IPGR1
|
||||
io.r_IPGR2 := IPGR2
|
||||
io.r_MinFL := minFL
|
||||
io.r_MaxFL := maxFL
|
||||
io.r_MaxRet := maxRet
|
||||
io.r_CollValid := collValid
|
||||
io.r_TxFlow := txFlow
|
||||
io.r_RxFlow := rxFlow
|
||||
io.r_PassAll := passAll
|
||||
io.r_MiiNoPre := miiNoPre
|
||||
io.r_ClkDiv := clkDiv
|
||||
io.r_WCtrlData := wCtrlData
|
||||
io.r_RStat := readStat
|
||||
io.r_ScanStat := scanStat
|
||||
io.r_RGAD := RGAD
|
||||
io.r_FIAD := FIAD
|
||||
io.r_CtrlData := MIITX_DATA
|
||||
|
||||
io.r_MAC := Cat( Mac_ADDR1(15,0), Mac_ADDR0(31,0) )
|
||||
io.r_HASH1 := HASH1
|
||||
io.r_HASH0 := HASH0
|
||||
io.r_TxBDNum := TX_BD_NUM
|
||||
io.r_TxPauseTV := txPauseTV
|
||||
io.r_TxPauseRq := txPauseRq
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
val SetTxCIrq_txclk_wire = Wire(Bool())
|
||||
val SetTxCIrq_sync1 = RegNext(SetTxCIrq_txclk_wire, false.B)
|
||||
val SetTxCIrq_sync2 = RegNext(SetTxCIrq_sync1, false.B)
|
||||
val SetTxCIrq_sync3 = RegNext(SetTxCIrq_sync2, false.B)
|
||||
val SetTxCIrq = RegNext(SetTxCIrq_sync2 & ~SetTxCIrq_sync3, false.B)
|
||||
|
||||
val SetRxCIrq_rxclk_wire = Wire(Bool())
|
||||
val SetRxCIrq_sync1 = RegNext(SetRxCIrq_rxclk_wire, false.B)
|
||||
val SetRxCIrq_sync2 = RegNext(SetRxCIrq_sync1, false.B)
|
||||
val SetRxCIrq_sync3 = RegNext(SetRxCIrq_sync2, false.B)
|
||||
val SetRxCIrq = RegNext(SetRxCIrq_sync2 & ~SetRxCIrq_sync3, false.B)
|
||||
|
||||
when(io.TxB_IRQ){ irq_txb := true.B }
|
||||
when(io.TxE_IRQ){ irq_txe := true.B }
|
||||
when(io.RxB_IRQ){ irq_rxb := true.B }
|
||||
when(io.RxE_IRQ){ irq_rxe := true.B }
|
||||
when(io.Busy_IRQ){ irq_busy := true.B }
|
||||
when(SetTxCIrq){ irq_txc := true.B }
|
||||
when(SetRxCIrq){ irq_rxc := true.B }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
withClockAndReset( io.TxClk.asClock, io.asyncReset ) {
|
||||
// val ResetTxCIrq_sync1 = Reg(Bool())
|
||||
val ResetTxCIrq_sync2 = RegNext(SetTxCIrq_sync1, false.B)
|
||||
val SetTxCIrq_txclk = RegInit(false.B); SetTxCIrq_txclk_wire := SetTxCIrq_txclk
|
||||
|
||||
// Synchronizing TxC Interrupt
|
||||
when(io.TxCtrlEndFrm & io.StartTxDone & io.r_TxFlow){
|
||||
SetTxCIrq_txclk := true.B
|
||||
} .elsewhen(ResetTxCIrq_sync2){
|
||||
SetTxCIrq_txclk := false.B
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
withClockAndReset( io.RxClk.asClock, io.asyncReset ) {
|
||||
val ResetRxCIrq_sync1 = RegNext(SetRxCIrq_sync2, false.B)
|
||||
val ResetRxCIrq_sync2 = RegNext(ResetRxCIrq_sync1, false.B)
|
||||
val ResetRxCIrq_sync3 = RegNext(ResetRxCIrq_sync2, false.B)
|
||||
val SetRxCIrq_rxclk = RegInit(false.B); SetRxCIrq_rxclk_wire := SetRxCIrq_rxclk
|
||||
|
||||
// Synchronizing RxC Interrupt
|
||||
when(io.SetPauseTimer & io.r_RxFlow){
|
||||
SetRxCIrq_rxclk := true.B
|
||||
} .elsewhen(ResetRxCIrq_sync2 & (~ResetRxCIrq_sync3)){
|
||||
SetRxCIrq_rxclk := false.B
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Generating interrupt signal
|
||||
// io.int_o :=
|
||||
int(0) :=
|
||||
(irq_txb & INT_MASK.extract(0) ) |
|
||||
(irq_txe & INT_MASK.extract(1) ) |
|
||||
(irq_rxb & INT_MASK.extract(2) ) |
|
||||
(irq_rxe & INT_MASK.extract(3) ) |
|
||||
(irq_busy & INT_MASK.extract(4) ) |
|
||||
(irq_txc & INT_MASK.extract(5) ) |
|
||||
(irq_rxc & INT_MASK.extract(6) )
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
379
src/main/scala/Switch/MacRx.scala
Normal file
379
src/main/scala/Switch/MacRx.scala
Normal file
@@ -0,0 +1,379 @@
|
||||
package MAC
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
|
||||
|
||||
class MacRxIO extends Bundle{
|
||||
|
||||
val MRxDV = Input(Bool())
|
||||
val MRxD = Input(UInt(4.W))
|
||||
val Transmitting = Input(Bool())
|
||||
val HugEn = Input(Bool())
|
||||
val DlyCrcEn = Input(Bool())
|
||||
val MaxFL = Input(UInt(16.W))
|
||||
val r_IFG = Input(Bool())
|
||||
val MAC = Input(UInt(48.W)) // Station Address
|
||||
val r_Bro = Input(Bool()) // broadcast disable
|
||||
val r_Pro = Input(Bool()) // promiscuous enable
|
||||
val r_HASH0 = Input(UInt(32.W)) // lower 4 bytes Hash Table
|
||||
val r_HASH1 = Input(UInt(32.W)) // upper 4 bytes Hash Table
|
||||
val PassAll = Input(Bool())
|
||||
val ControlFrmAddressOK = Input(Bool())
|
||||
|
||||
val RxData = Output(UInt(8.W))
|
||||
val RxValid = Output(Bool())
|
||||
val RxStartFrm = Output(Bool())
|
||||
val RxEndFrm = Output(Bool())
|
||||
val ByteCnt = Output(UInt(16.W))
|
||||
val ByteCntEq0 = Output(Bool())
|
||||
val ByteCntGreat2 = Output(Bool())
|
||||
val ByteCntMaxFrame = Output(Bool())
|
||||
val CrcError = Output(Bool())
|
||||
val StateIdle = Output(Bool())
|
||||
val StatePreamble = Output(Bool())
|
||||
val StateSFD = Output(Bool())
|
||||
val StateData = Output(UInt(2.W))
|
||||
val RxAbort = Output(Bool())
|
||||
val AddressMiss = Output(Bool())
|
||||
}
|
||||
|
||||
|
||||
abstract class MacRxBase extends Module with RequireAsyncReset{
|
||||
val io: MacRxIO = IO(new MacRxIO)
|
||||
|
||||
val MRxDEqD = io.MRxD === "hd".U
|
||||
val MRxDEq5 = io.MRxD === "h5".U
|
||||
|
||||
val IFGCounterEq24 = Wire(Bool())
|
||||
|
||||
val ByteCntEq0 = Wire(Bool())
|
||||
io.ByteCntEq0 := ByteCntEq0
|
||||
|
||||
val ByteCntEq1 = Wire(Bool())
|
||||
val ByteCntEq2 = Wire(Bool())
|
||||
val ByteCntEq3 = Wire(Bool())
|
||||
val ByteCntEq4 = Wire(Bool())
|
||||
val ByteCntEq5 = Wire(Bool())
|
||||
val ByteCntEq6 = Wire(Bool())
|
||||
val ByteCntEq7 = Wire(Bool())
|
||||
|
||||
val ByteCntSmall7 = Wire(Bool())
|
||||
|
||||
val DlyCrcCnt = RegInit(0.U(4.W))
|
||||
|
||||
val StateData0 = RegInit(false.B)
|
||||
val StateData1 = RegInit(false.B)
|
||||
val StateIdle = RegInit(false.B); io.StateIdle := StateIdle
|
||||
val StateDrop = RegInit(true.B)
|
||||
val StatePreamble = RegInit(false.B); io.StatePreamble := StatePreamble
|
||||
val StateSFD = RegInit(false.B); io.StateSFD := StateSFD
|
||||
|
||||
val RxData_d = RegInit(0.U(8.W))
|
||||
val RxData = RegNext(RxData_d, 0.U); io.RxData := RxData
|
||||
|
||||
val Broadcast = RegInit(false.B)
|
||||
val Multicast = RegInit(false.B)
|
||||
|
||||
val Crc = RegInit("hFFFFFFFF".U(32.W))
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
trait MacRxFSM { this: MacRxBase =>
|
||||
|
||||
val StateData = Cat( StateData1, StateData0 )
|
||||
io.StateData := StateData
|
||||
|
||||
// Defining the next state
|
||||
val StartIdle = ~io.MRxDV & (StateDrop | StatePreamble | StateSFD | StateData0 | StateData1 )
|
||||
val StartPreamble = io.MRxDV & ~MRxDEq5 & (StateIdle & ~io.Transmitting)
|
||||
val StartSFD = io.MRxDV & MRxDEq5 & (StateIdle & ~io.Transmitting | StatePreamble)
|
||||
val StartData0 = io.MRxDV & (StateSFD & MRxDEqD & IFGCounterEq24 | StateData1)
|
||||
val StartData1 = io.MRxDV & StateData0 & (~io.ByteCntMaxFrame)
|
||||
val StartDrop = io.MRxDV & (
|
||||
(StateIdle & io.Transmitting) | (StateSFD & ~IFGCounterEq24 & MRxDEqD ) | ( StateData0 & io.ByteCntMaxFrame)
|
||||
)
|
||||
|
||||
|
||||
when(StartPreamble | StartSFD | StartDrop){
|
||||
StateIdle := false.B
|
||||
} .elsewhen( StartIdle ){
|
||||
StateIdle := true.B
|
||||
}
|
||||
|
||||
when( StartIdle ){
|
||||
StateDrop := false.B
|
||||
} .elsewhen(StartDrop){
|
||||
StateDrop := true.B
|
||||
}
|
||||
|
||||
when(StartSFD | StartIdle | StartDrop ){
|
||||
StatePreamble := false.B
|
||||
} .elsewhen(StartPreamble){
|
||||
StatePreamble := true.B
|
||||
}
|
||||
|
||||
when(StartPreamble | StartIdle | StartData0 | StartDrop){
|
||||
StateSFD := false.B
|
||||
} .elsewhen (StartSFD){
|
||||
StateSFD := true.B
|
||||
}
|
||||
|
||||
|
||||
when(StartIdle | StartData1 | StartDrop){
|
||||
StateData0 := false.B
|
||||
} .elsewhen(StartData0){
|
||||
StateData0 := true.B
|
||||
}
|
||||
|
||||
|
||||
when(StartIdle | StartData0 | StartDrop){
|
||||
StateData1 := false.B
|
||||
} .elsewhen(StartData1){
|
||||
StateData1 := true.B
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
trait MacRxCounter { this: MacRxBase =>
|
||||
|
||||
val ByteCnt = RegInit(0.U(16.W))
|
||||
val IFGCounter = RegInit(0.U(5.W))
|
||||
|
||||
val ByteCntMax = ByteCnt === "hffff".U
|
||||
|
||||
val ResetByteCounter = io.MRxDV & (io.StateSFD & MRxDEqD | io.StateData.extract(0) & io.ByteCntMaxFrame)
|
||||
|
||||
val IncrementByteCounter =
|
||||
~ResetByteCounter & io.MRxDV & (
|
||||
io.StatePreamble | io.StateSFD | io.StateIdle & ~io.Transmitting |
|
||||
(io.StateData.extract(1) & ~ByteCntMax & ~(io.DlyCrcEn & DlyCrcCnt.orR))
|
||||
)
|
||||
|
||||
val ByteCntDelayed = ByteCnt + 4.U
|
||||
io.ByteCnt := Mux(io.DlyCrcEn, ByteCntDelayed, ByteCnt)
|
||||
|
||||
when( DlyCrcCnt === 9.U ){
|
||||
DlyCrcCnt := 0.U
|
||||
} .elsewhen(io.DlyCrcEn & io.StateSFD){
|
||||
DlyCrcCnt := 1.U
|
||||
} .elsewhen(io.DlyCrcEn & (DlyCrcCnt.orR)){
|
||||
DlyCrcCnt := DlyCrcCnt + 1.U
|
||||
}
|
||||
|
||||
when( ResetByteCounter ){
|
||||
ByteCnt := 0.U
|
||||
} .elsewhen(IncrementByteCounter){
|
||||
ByteCnt := ByteCnt + 1.U
|
||||
}
|
||||
|
||||
ByteCntEq0 := ByteCnt === 0.U
|
||||
ByteCntEq1 := ByteCnt === 1.U
|
||||
ByteCntEq2 := ByteCnt === 2.U
|
||||
ByteCntEq3 := ByteCnt === 3.U
|
||||
ByteCntEq4 := ByteCnt === 4.U
|
||||
ByteCntEq5 := ByteCnt === 5.U
|
||||
ByteCntEq6 := ByteCnt === 6.U
|
||||
ByteCntEq7 := ByteCnt === 7.U
|
||||
|
||||
io.ByteCntGreat2 := ByteCnt > 2.U
|
||||
ByteCntSmall7 := ByteCnt < 7.U
|
||||
|
||||
io.ByteCntMaxFrame := (ByteCnt === io.MaxFL) & ~io.HugEn;
|
||||
|
||||
|
||||
val ResetIFGCounter = io.StateSFD & io.MRxDV & MRxDEqD | StateDrop;
|
||||
val IncrementIFGCounter = ~ResetIFGCounter & (StateDrop | io.StateIdle | io.StatePreamble | io.StateSFD) & ~IFGCounterEq24;
|
||||
|
||||
when( ResetIFGCounter ){
|
||||
IFGCounter := 0.U
|
||||
} .elsewhen(IncrementIFGCounter){
|
||||
IFGCounter := IFGCounter + 1.U
|
||||
}
|
||||
|
||||
IFGCounterEq24 := (IFGCounter === "h18".U) | io.r_IFG; // 24*400 = 9600 ns or r_IFG is set to 1
|
||||
|
||||
}
|
||||
|
||||
trait MacRxFAddrCheck { this: MacRxBase =>
|
||||
|
||||
val HashBit = Wire(UInt(1.W))
|
||||
|
||||
|
||||
val BroadcastOK = Broadcast & ~io.r_Bro
|
||||
val RxCheckEn = io.StateData.orR
|
||||
|
||||
val RxAbort = RegInit(false.B) // Address Error Reported at end of address cycle// RxAbort clears after one cycle
|
||||
val AddressMiss = RegInit(false.B) // This ff holds the "Address Miss" information that is written to the RX BD status.
|
||||
val MulticastOK = RegInit(false.B) // Hash Address Check, Multicast
|
||||
val UnicastOK = RegInit(false.B) // Address Detection (unicast) // start with ByteCntEq2 due to delay of addres from RxData
|
||||
|
||||
io.RxAbort := RxAbort
|
||||
io.AddressMiss := AddressMiss
|
||||
|
||||
|
||||
val RxAddressInvalid = ~(UnicastOK | BroadcastOK | MulticastOK | io.r_Pro);
|
||||
|
||||
val CrcHash = RegInit(0.U(6.W))
|
||||
val CrcHashGood = RegNext(StateData0 & ByteCntEq6) // Latching CRC for use in the hash table
|
||||
|
||||
when(RxAddressInvalid & ByteCntEq7 & RxCheckEn){
|
||||
RxAbort := true.B
|
||||
} .otherwise{
|
||||
RxAbort := false.B
|
||||
}
|
||||
|
||||
when(ByteCntEq0){
|
||||
AddressMiss := false.B
|
||||
} .elsewhen(ByteCntEq7 & RxCheckEn){
|
||||
AddressMiss := (~(UnicastOK | BroadcastOK | MulticastOK | (io.PassAll & io.ControlFrmAddressOK)));
|
||||
}
|
||||
|
||||
when(io.RxEndFrm | RxAbort){
|
||||
MulticastOK := false.B
|
||||
} .elsewhen(CrcHashGood & Multicast){
|
||||
MulticastOK := HashBit
|
||||
}
|
||||
|
||||
when(RxCheckEn & ByteCntEq2){
|
||||
UnicastOK := RxData === io.MAC(47,40)
|
||||
} .elsewhen(RxCheckEn & ByteCntEq3){
|
||||
UnicastOK := ( RxData === io.MAC(39,32)) & UnicastOK
|
||||
} .elsewhen(RxCheckEn & ByteCntEq4){
|
||||
UnicastOK := ( RxData === io.MAC(31,24)) & UnicastOK
|
||||
} .elsewhen(RxCheckEn & ByteCntEq5){
|
||||
UnicastOK := ( RxData === io.MAC(23,16)) & UnicastOK
|
||||
} .elsewhen(RxCheckEn & ByteCntEq6){
|
||||
UnicastOK := ( RxData === io.MAC(15,8)) & UnicastOK
|
||||
} .elsewhen(RxCheckEn & ByteCntEq7){
|
||||
UnicastOK := ( RxData === io.MAC(7,0)) & UnicastOK
|
||||
} .elsewhen(io.RxEndFrm | RxAbort){
|
||||
UnicastOK := false.B
|
||||
}
|
||||
|
||||
|
||||
val IntHash = Mux(CrcHash.extract(5), io.r_HASH1, io.r_HASH0)
|
||||
val ByteHash =
|
||||
Mux1H(Seq(
|
||||
(CrcHash(4,3) === "b00".U) -> IntHash(7 ,0),
|
||||
(CrcHash(4,3) === "b01".U) -> IntHash(15,8),
|
||||
(CrcHash(4,3) === "b10".U) -> IntHash(23,16),
|
||||
(CrcHash(4,3) === "b11".U) -> IntHash(31,24),
|
||||
))
|
||||
|
||||
HashBit := ByteHash >> CrcHash(2,0)
|
||||
|
||||
when(StateIdle){
|
||||
CrcHash := 0.U
|
||||
} .elsewhen(StateData0 & ByteCntEq6){
|
||||
CrcHash := Crc(31,26)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
trait MacRxCRC { this: MacRxBase =>
|
||||
|
||||
val Data_Crc = Cat(io.MRxD.extract(0),io.MRxD.extract(1),io.MRxD.extract(2),io.MRxD.extract(3))
|
||||
val Enable_Crc = io.MRxDV & (io.StateData.orR & ~io.ByteCntMaxFrame)
|
||||
val Initialize_Crc = io.StateSFD | (io.DlyCrcEn & DlyCrcCnt > 0.U & DlyCrcCnt < 9.U)
|
||||
|
||||
when( Initialize_Crc ){
|
||||
Crc := "hFFFFFFFF".U
|
||||
} .otherwise{
|
||||
Crc := Cat(
|
||||
Crc.extract(27),
|
||||
Crc.extract(26),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(25),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Crc.extract(30))) ^ Crc.extract(24),
|
||||
(Enable_Crc & (Data_Crc.extract(1) ^ Crc.extract(29))) ^ Crc.extract(23),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(0) ^ Crc.extract(31) ^ Crc.extract(28))) ^ Crc.extract(22),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Crc.extract(31) ^ Crc.extract(30))) ^ Crc.extract(21),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(30) ^ Crc.extract(29))) ^ Crc.extract(20),
|
||||
(Enable_Crc & (Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(29) ^ Crc.extract(28))) ^ Crc.extract(19),
|
||||
(Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))) ^ Crc.extract(18),
|
||||
Crc.extract(17),
|
||||
Crc.extract(16),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(15),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Crc.extract(30))) ^ Crc.extract(14),
|
||||
(Enable_Crc & (Data_Crc.extract(1) ^ Crc.extract(29))) ^ Crc.extract(13),
|
||||
(Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))) ^ Crc.extract(12),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(11),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(10),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(9),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract(8),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(7),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(6),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract(5),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(4),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(3),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract( 2),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(1),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(0),
|
||||
Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30) ^ Crc.extract(31)),
|
||||
Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(30)),
|
||||
Enable_Crc & (Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29)),
|
||||
Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))
|
||||
)
|
||||
}
|
||||
|
||||
io.CrcError := Crc =/= "hc704dd7b".U // CRC not equal to magic number
|
||||
|
||||
|
||||
}
|
||||
|
||||
class MacRx extends MacRxBase with MacRxFSM with MacRxCounter with MacRxFAddrCheck with MacRxCRC{
|
||||
|
||||
|
||||
|
||||
val GenerateRxValid = StateData0 & (~ByteCntEq0 | DlyCrcCnt >= 3.U);
|
||||
val DelayData = RegNext(StateData0, false.B)
|
||||
val LatchedByte = RegInit(0.U(8.W))
|
||||
when(true.B) {
|
||||
LatchedByte := Cat(io.MRxD, LatchedByte(7,4))// Latched byte
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Output byte stream
|
||||
when( GenerateRxValid ){
|
||||
RxData_d := LatchedByte & Fill(8, StateData0 | StateData1) // Data goes through only in data state
|
||||
} .elsewhen(~DelayData){
|
||||
RxData_d := 0.U // Delaying data to be valid for two cycles. // Zero when not active.
|
||||
}
|
||||
|
||||
|
||||
when(StateData0 & LatchedByte =/= "hFF".U & ByteCntSmall7){
|
||||
Broadcast := false.B
|
||||
} .elsewhen(StateData0 & LatchedByte === "hFF".U & ByteCntEq1){
|
||||
Broadcast := true.B
|
||||
} .elsewhen(io.RxAbort | io.RxEndFrm){
|
||||
Broadcast := false.B
|
||||
}
|
||||
|
||||
|
||||
when(StateData0 & ByteCntEq1 & LatchedByte.extract(0)){
|
||||
Multicast := true.B
|
||||
} .elsewhen(io.RxAbort | io.RxEndFrm){
|
||||
Multicast := false.B
|
||||
}
|
||||
|
||||
|
||||
|
||||
io.RxValid := ShiftRegister(GenerateRxValid, 2, false.B, true.B)
|
||||
|
||||
|
||||
val GenerateRxStartFrm = StateData0 & ( (ByteCntEq1 & ~io.DlyCrcEn) | ((DlyCrcCnt === 3.U) & io.DlyCrcEn) )
|
||||
|
||||
io.RxStartFrm := ShiftRegister(GenerateRxStartFrm, 2, false.B, true.B)
|
||||
|
||||
|
||||
val GenerateRxEndFrm = StateData0 & ((~io.MRxDV & io.ByteCntGreat2) | io.ByteCntMaxFrame)
|
||||
val DribbleRxEndFrm = StateData1 & ~io.MRxDV & io.ByteCntGreat2
|
||||
|
||||
val RxEndFrm_d = RegNext(GenerateRxEndFrm, false.B)
|
||||
io.RxEndFrm := RegNext(RxEndFrm_d | DribbleRxEndFrm, false.B)
|
||||
|
||||
}
|
||||
479
src/main/scala/Switch/MacTx.scala
Normal file
479
src/main/scala/Switch/MacTx.scala
Normal file
@@ -0,0 +1,479 @@
|
||||
package MAC
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
|
||||
class MacTxIO extends Bundle{
|
||||
|
||||
val TxStartFrm = Input(Bool()) // Transmit packet start frame
|
||||
val TxEndFrm = Input(Bool()) // Transmit packet end frame
|
||||
val TxData = Input(UInt(8.W)) // Transmit packet data byte
|
||||
val CarrierSense = Input(Bool()) // Carrier sense (synchronized)
|
||||
val Collision = Input(Bool()) // Collision (synchronized)
|
||||
val Pad = Input(Bool()) // Pad enable (from register)
|
||||
val CrcEn = Input(Bool()) // Crc enable (from register)
|
||||
val FullD = Input(Bool()) // Full duplex (from register)
|
||||
val HugEn = Input(Bool()) // Huge packets enable (from register)
|
||||
val DlyCrcEn = Input(Bool()) // Delayed Crc enabled (from register)
|
||||
val MinFL = Input(UInt(16.W)) // Minimum frame length (from register)
|
||||
val MaxFL = Input(UInt(16.W)) // Maximum frame length (from register)
|
||||
val IPGT = Input(UInt(7.W)) // Back to back transmit inter packet gap parameter (from register)
|
||||
val IPGR1 = Input(UInt(7.W)) // Non back to back transmit inter packet gap parameter IPGR1 (from register)
|
||||
val IPGR2 = Input(UInt(7.W)) // Non back to back transmit inter packet gap parameter IPGR2 (from register)
|
||||
val CollValid = Input(UInt(6.W)) // Valid collision window (from register)
|
||||
val MaxRet = Input(UInt(4.W)) // Maximum retry number (from register)
|
||||
val NoBckof = Input(Bool()) // No backoff (from register)
|
||||
val ExDfrEn = Input(Bool()) // Excessive defferal enable (from register)
|
||||
|
||||
val MTxD = Output(UInt(4.W)) // Transmit nibble (to PHY)
|
||||
val MTxEn = Output(Bool()) // Transmit enable (to PHY)
|
||||
val MTxErr = Output(Bool()) // Transmit error (to PHY)
|
||||
val TxDone = Output(Bool()) // Transmit packet done (to RISC)
|
||||
val TxRetry = Output(Bool()) // Transmit packet retry (to RISC)
|
||||
val TxAbort = Output(Bool()) // Transmit packet abort (to RISC)
|
||||
val TxUsedData = Output(Bool()) // Transmit packet used data (to RISC)
|
||||
val WillTransmit = Output(Bool()) // Will transmit (to RxEthMAC)
|
||||
val ResetCollision = Output(Bool()) // Reset Collision (for synchronizing collision)
|
||||
val RetryCnt = Output(UInt(4.W)) // Latched Retry Counter for tx status purposes
|
||||
val StartTxDone = Output(Bool())
|
||||
val StartTxAbort = Output(Bool())
|
||||
val MaxCollisionOccured= Output(Bool())
|
||||
val LateCollision = Output(Bool())
|
||||
val DeferIndication = Output(Bool())
|
||||
val StatePreamble = Output(Bool())
|
||||
val StateData = Output(UInt(2.W))
|
||||
}
|
||||
|
||||
abstract class MacTxBase extends Module with RequireAsyncReset{
|
||||
val io: MacTxIO = IO(new MacTxIO)
|
||||
|
||||
|
||||
|
||||
|
||||
val StartIPG = Wire(Bool())
|
||||
val StartPreamble = Wire(Bool())
|
||||
val StartData = Wire( Vec(2,Bool()))
|
||||
val StartFCS = Wire(Bool())
|
||||
val StartJam = Wire(Bool())
|
||||
val StartDefer = Wire(Bool())
|
||||
val StartBackoff = Wire(Bool())
|
||||
|
||||
|
||||
|
||||
|
||||
val StateSFD = Wire(Bool())
|
||||
|
||||
val TooBig = Wire(Bool())
|
||||
|
||||
val CrcError = Wire(Bool())
|
||||
|
||||
|
||||
val NibbleMinFl = Wire(Bool())
|
||||
val ExcessiveDefer = Wire(Bool())
|
||||
|
||||
val MaxFrame = Wire(Bool())
|
||||
val RetryMax = Wire(Bool())
|
||||
val RandomEq0 = Wire(Bool())
|
||||
val RandomEqByteCnt = Wire(Bool())
|
||||
|
||||
val StateIPG = RegInit(false.B)
|
||||
val StateIdle = RegInit(false.B)
|
||||
val StatePreamble = RegInit(false.B); io.StatePreamble := StatePreamble
|
||||
val StateData = RegNext( Cat(StartData(1), StartData(0)), 0.U(2.W)); io.StateData := StateData
|
||||
val StatePAD = RegInit(false.B)
|
||||
val StateFCS = RegInit(false.B)
|
||||
val StateJam = RegInit(false.B)
|
||||
val StateJam_q = RegNext(StateJam, false.B)
|
||||
val StateBackOff = RegInit(false.B)
|
||||
val StateDefer = RegInit(true.B)
|
||||
val Rule1 = RegInit(false.B)
|
||||
|
||||
val ColWindow = RegInit(true.B)
|
||||
val DlyCrcCnt = RegInit(0.U(3.W)) // Delayed CRC counter
|
||||
val PacketFinished_q = RegInit(false.B)
|
||||
val ByteCnt = RegInit(0.U(16.W)) // Transmit Byte Counter
|
||||
val NibCnt = RegInit(0.U(16.W)) // Nibble Counter
|
||||
val NibCntEq7 = NibCnt === 7.U
|
||||
val NibCntEq15 = NibCnt === 15.U
|
||||
|
||||
val RetryCnt = RegInit(0.U(4.W)); io.RetryCnt := RetryCnt
|
||||
}
|
||||
|
||||
|
||||
|
||||
trait MacTxFSM { this: MacTxBase =>
|
||||
|
||||
// Defining the next state
|
||||
StartIPG := StateDefer & ~ExcessiveDefer & ~io.CarrierSense
|
||||
|
||||
val StartIdle = StateIPG & (Rule1 & NibCnt(6,0) >= io.IPGT | ~Rule1 & NibCnt(6,0) >= io.IPGR2)
|
||||
|
||||
StartPreamble := StateIdle & io.TxStartFrm & ~io.CarrierSense
|
||||
|
||||
StartData(0) := ~io.Collision & (StatePreamble & NibCntEq15 | StateData(1) & ~io.TxEndFrm)
|
||||
StartData(1) := ~io.Collision & StateData(0) & ~MaxFrame
|
||||
|
||||
val StartPAD = ~io.Collision & StateData(1) & io.TxEndFrm & io.Pad & ~NibbleMinFl
|
||||
|
||||
StartFCS :=
|
||||
(~io.Collision & StateData(1) & io.TxEndFrm & (~io.Pad | io.Pad & NibbleMinFl) & io.CrcEn) |
|
||||
(~io.Collision & StatePAD & NibbleMinFl & io.CrcEn)
|
||||
|
||||
StartJam := (io.Collision ) & ((StatePreamble & NibCntEq15) | (StateData(1) | StateData(0)) | StatePAD | StateFCS)
|
||||
|
||||
StartBackoff := StateJam & ~RandomEq0 & ColWindow & ~RetryMax & NibCntEq7 & ~io.NoBckof
|
||||
|
||||
StartDefer :=
|
||||
(StateIPG & ~Rule1 & io.CarrierSense & NibCnt(6,0) <= io.IPGR1 & NibCnt(6,0) =/= io.IPGR2) |
|
||||
(StateIdle & io.CarrierSense) |
|
||||
(StateJam & NibCntEq7 & (io.NoBckof | RandomEq0 | ~ColWindow | RetryMax)) |
|
||||
(StateBackOff & (RandomEqByteCnt)) |
|
||||
io.StartTxDone |
|
||||
TooBig
|
||||
|
||||
io.DeferIndication := StateIdle & io.CarrierSense
|
||||
|
||||
|
||||
|
||||
when(StartDefer | StartIdle){
|
||||
StateIPG := false.B
|
||||
}.elsewhen(StartIPG){
|
||||
StateIPG := true.B
|
||||
}
|
||||
|
||||
when(StartDefer | StartPreamble){
|
||||
StateIdle := false.B
|
||||
}.elsewhen(StartIdle){
|
||||
StateIdle := true.B
|
||||
}
|
||||
|
||||
when(StartData(0) | StartJam){
|
||||
StatePreamble := false.B
|
||||
} .elsewhen(StartPreamble){
|
||||
StatePreamble := true.B
|
||||
}
|
||||
|
||||
when(StartFCS | StartJam){
|
||||
StatePAD := false.B
|
||||
}.elsewhen(StartPAD){
|
||||
StatePAD := true.B
|
||||
}
|
||||
|
||||
when(StartJam | StartDefer){
|
||||
StateFCS := false.B
|
||||
} .elsewhen(StartFCS){
|
||||
StateFCS := true.B
|
||||
}
|
||||
|
||||
when(StartBackoff | StartDefer){
|
||||
StateJam := false.B
|
||||
} .elsewhen(StartJam){
|
||||
StateJam := true.B
|
||||
}
|
||||
|
||||
when(StartDefer){
|
||||
StateBackOff := false.B
|
||||
} .elsewhen(StartBackoff){
|
||||
StateBackOff := true.B
|
||||
}
|
||||
|
||||
when(StartIPG){
|
||||
StateDefer := false.B
|
||||
} .elsewhen(StartDefer){
|
||||
StateDefer := true.B
|
||||
}
|
||||
|
||||
// This sections defines which interpack gap rule to use
|
||||
when(StateIdle | StateBackOff){
|
||||
Rule1 := false.B
|
||||
} .elsewhen(StatePreamble | io.FullD){
|
||||
Rule1 := true.B
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
trait MacTxCounter { this: MacTxBase =>
|
||||
|
||||
val ByteCntMax = Wire(Bool())
|
||||
|
||||
val IncrementNibCnt =
|
||||
StateIPG | StatePreamble |
|
||||
(StateData(1) | StateData(0)) |
|
||||
StatePAD | StateFCS | StateJam | StateBackOff |
|
||||
(StateDefer & ~ExcessiveDefer & io.TxStartFrm)
|
||||
|
||||
|
||||
val ResetNibCnt =
|
||||
(StateDefer & ExcessiveDefer & ~io.TxStartFrm) |
|
||||
(StatePreamble & NibCntEq15) |
|
||||
(StateJam & NibCntEq7) |
|
||||
StateIdle | StartDefer | StartIPG | StartFCS | StartJam
|
||||
|
||||
|
||||
when(ResetNibCnt){
|
||||
NibCnt := 0.U
|
||||
} .elsewhen(IncrementNibCnt){
|
||||
NibCnt := NibCnt + 1.U
|
||||
}
|
||||
|
||||
NibbleMinFl := NibCnt >= (((io.MinFL-4.U)<<1) - 1.U) // FCS should not be included in NibbleMinFl
|
||||
|
||||
ExcessiveDefer := NibCnt(13,0) === "h17b7".U & ~io.ExDfrEn; // 6071 nibbles
|
||||
|
||||
val IncrementByteCnt =
|
||||
(StateData(1) & ~ByteCntMax) |
|
||||
(StateBackOff & (NibCnt(6,0) === 127.U)) |
|
||||
((StatePAD | StateFCS) & NibCnt.extract(0) & ~ByteCntMax)
|
||||
|
||||
val ResetByteCnt =
|
||||
StartBackoff |
|
||||
(StateIdle & io.TxStartFrm) |
|
||||
PacketFinished_q
|
||||
|
||||
|
||||
ByteCntMax := ByteCnt.andR
|
||||
when(ResetByteCnt){
|
||||
ByteCnt := 0.U
|
||||
} .elsewhen(IncrementByteCnt){
|
||||
ByteCnt := ByteCnt + 1.U
|
||||
}
|
||||
|
||||
MaxFrame := (ByteCnt === io.MaxFL) & ~io.HugEn;
|
||||
|
||||
when((StateData(1) & DlyCrcCnt === 4.U) | StartJam | PacketFinished_q){
|
||||
DlyCrcCnt := 0.U
|
||||
}.elsewhen(io.DlyCrcEn & (StateSFD | StateData(1) & (DlyCrcCnt.orR))){
|
||||
DlyCrcCnt := DlyCrcCnt + 1.U
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
trait MacTxCRC{ this: MacTxBase =>
|
||||
|
||||
val Initialize_Crc = StateIdle | StatePreamble | (DlyCrcCnt.orR)
|
||||
val Enable_Crc = ~StateFCS
|
||||
|
||||
val Data_Crc =
|
||||
Mux1H(Seq(
|
||||
StateData(0) -> Cat( io.TxData(0), io.TxData(1), io.TxData(2), io.TxData(3) ),
|
||||
StateData(1) -> Cat( io.TxData(4), io.TxData(5), io.TxData(6), io.TxData(7) ),
|
||||
))
|
||||
|
||||
val Crc = RegInit("hFFFFFFFF".U(32.W))
|
||||
|
||||
when( Initialize_Crc ){
|
||||
Crc := "hFFFFFFFF".U
|
||||
} .otherwise{
|
||||
Crc := Cat(
|
||||
Crc.extract(27),
|
||||
Crc.extract(26),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(25),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Crc.extract(30))) ^ Crc.extract(24),
|
||||
(Enable_Crc & (Data_Crc.extract(1) ^ Crc.extract(29))) ^ Crc.extract(23),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(0) ^ Crc.extract(31) ^ Crc.extract(28))) ^ Crc.extract(22),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Crc.extract(31) ^ Crc.extract(30))) ^ Crc.extract(21),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(30) ^ Crc.extract(29))) ^ Crc.extract(20),
|
||||
(Enable_Crc & (Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(29) ^ Crc.extract(28))) ^ Crc.extract(19),
|
||||
(Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))) ^ Crc.extract(18),
|
||||
Crc.extract(17),
|
||||
Crc.extract(16),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(15),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Crc.extract(30))) ^ Crc.extract(14),
|
||||
(Enable_Crc & (Data_Crc.extract(1) ^ Crc.extract(29))) ^ Crc.extract(13),
|
||||
(Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))) ^ Crc.extract(12),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Crc.extract(31))) ^ Crc.extract(11),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(10),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(9),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract(8),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(7),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(6),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract(5),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(4),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(3),
|
||||
(Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30))) ^ Crc.extract( 2),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(31))) ^ Crc.extract(1),
|
||||
(Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(30) ^ Crc.extract(31))) ^ Crc.extract(0),
|
||||
Enable_Crc & (Data_Crc.extract(3) ^ Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Crc.extract(29) ^ Crc.extract(30) ^ Crc.extract(31)),
|
||||
Enable_Crc & (Data_Crc.extract(2) ^ Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29) ^ Crc.extract(30)),
|
||||
Enable_Crc & (Data_Crc.extract(1) ^ Data_Crc.extract(0) ^ Crc.extract(28) ^ Crc.extract(29)),
|
||||
Enable_Crc & (Data_Crc.extract(0) ^ Crc.extract(28))
|
||||
)
|
||||
}
|
||||
|
||||
CrcError := Crc =/= "hc704dd7b".U // CRC not equal to magic number
|
||||
|
||||
|
||||
}
|
||||
|
||||
trait MacTxRandom{ this: MacTxBase =>
|
||||
|
||||
val x = RegInit(0.U(10.W))
|
||||
when(true.B){
|
||||
x := Cat( x(8,0), ~(x.extract(2) ^ x.extract(9)) )
|
||||
}
|
||||
|
||||
val RandomLatched = RegEnable(
|
||||
Cat(
|
||||
Mux( RetryCnt > 9.U, x.extract(9), 0.U(1.W)),
|
||||
Mux( RetryCnt > 8.U, x.extract(8), 0.U(1.W)),
|
||||
Mux( RetryCnt > 7.U, x.extract(7), 0.U(1.W)),
|
||||
Mux( RetryCnt > 6.U, x.extract(6), 0.U(1.W)),
|
||||
Mux( RetryCnt > 5.U, x.extract(5), 0.U(1.W)),
|
||||
Mux( RetryCnt > 4.U, x.extract(4), 0.U(1.W)),
|
||||
Mux( RetryCnt > 3.U, x.extract(3), 0.U(1.W)),
|
||||
Mux( RetryCnt > 2.U, x.extract(2), 0.U(1.W)),
|
||||
Mux( RetryCnt > 1.U, x.extract(1), 0.U(1.W)),
|
||||
x.extract(0)
|
||||
),
|
||||
0.U(10.W),
|
||||
StateJam & StateJam_q
|
||||
)
|
||||
|
||||
// Random Number == 0 IEEE 802.3 page 68. If 0 we go to defer and not to backoff.
|
||||
RandomEq0 := RandomLatched === 0.U
|
||||
RandomEqByteCnt := ByteCnt(9,0) === RandomLatched & (NibCnt(6,0).andR)
|
||||
|
||||
}
|
||||
|
||||
class MacTx extends MacTxBase with MacTxFSM with MacTxCounter with MacTxCRC with MacTxRandom{
|
||||
val MTxD = RegInit(0.U(4.W)); io.MTxD := MTxD
|
||||
val StopExcessiveDeferOccured = RegInit(false.B)
|
||||
|
||||
val StatusLatch = RegInit(false.B)
|
||||
val TxUsedData = RegNext(StartData(0) | StartData(1), false.B); io.TxUsedData := TxUsedData
|
||||
val TxDone = RegInit(false.B); io.TxDone := TxDone
|
||||
val TxRetry = RegInit(false.B); io.TxRetry := TxRetry
|
||||
val TxAbort = RegInit(false.B); io.TxAbort := TxAbort
|
||||
|
||||
val MTxEn = RegNext(StatePreamble | (StateData(0) | StateData(1)) | StatePAD | StateFCS | StateJam, false.B); io.MTxEn := MTxEn
|
||||
val MTxErr = RegNext( TooBig, false.B); io.MTxErr := MTxErr// Transmit error
|
||||
|
||||
val WillTransmit = RegNext(StartPreamble | StatePreamble | (StateData(0) | StateData(1)) | StatePAD | StateFCS | StateJam, false.B); io.WillTransmit := WillTransmit// WillTransmit
|
||||
|
||||
|
||||
|
||||
io.ResetCollision := ~(StatePreamble | (StateData(0) | StateData(1)) | StatePAD | StateFCS)
|
||||
val ExcessiveDeferOccured = io.TxStartFrm & StateDefer & ExcessiveDefer & ~StopExcessiveDeferOccured
|
||||
io.StartTxDone := ~io.Collision & (StateFCS & NibCntEq7 | StateData(1) & io.TxEndFrm & (~io.Pad | io.Pad & NibbleMinFl) & ~io.CrcEn)
|
||||
TooBig := ~io.Collision & MaxFrame & (StateData(0) | StateFCS);
|
||||
val StartTxRetry = StartJam & (ColWindow & ~RetryMax)
|
||||
io.LateCollision := StartJam & ~ColWindow
|
||||
io.MaxCollisionOccured := StartJam & ColWindow & RetryMax;
|
||||
StateSFD := StatePreamble & NibCntEq15;
|
||||
io.StartTxAbort := TooBig | ExcessiveDeferOccured | io.LateCollision | io.MaxCollisionOccured
|
||||
|
||||
when(~io.TxStartFrm){
|
||||
StopExcessiveDeferOccured := false.B
|
||||
}.elsewhen(ExcessiveDeferOccured){
|
||||
StopExcessiveDeferOccured := true.B
|
||||
}
|
||||
|
||||
|
||||
// Collision Window
|
||||
when(~io.Collision & ByteCnt(5,0) === io.CollValid & (StateData(1) | StatePAD & NibCnt.extract(0) | StateFCS & NibCnt.extract(0))){
|
||||
ColWindow := false.B
|
||||
} .elsewhen(StateIdle | StateIPG){
|
||||
ColWindow := true.B
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Start Window
|
||||
when(~io.TxStartFrm){
|
||||
StatusLatch := false.B
|
||||
} .elsewhen(ExcessiveDeferOccured | StateIdle){
|
||||
StatusLatch := true.B
|
||||
}
|
||||
|
||||
|
||||
// Transmit packet done
|
||||
when(io.TxStartFrm & ~StatusLatch){
|
||||
TxDone := false.B
|
||||
}.elsewhen(io.StartTxDone){
|
||||
TxDone := true.B
|
||||
}
|
||||
|
||||
// Transmit packet retry
|
||||
when(io.TxStartFrm & ~StatusLatch){
|
||||
TxRetry := false.B
|
||||
} .elsewhen(StartTxRetry){
|
||||
TxRetry := true.B
|
||||
}
|
||||
|
||||
|
||||
// Transmit packet abort
|
||||
when(io.TxStartFrm & ~StatusLatch & ~ExcessiveDeferOccured){
|
||||
TxAbort := false.B
|
||||
} .elsewhen(io.StartTxAbort){
|
||||
TxAbort := true.B
|
||||
}
|
||||
|
||||
// Retry counter
|
||||
when(ExcessiveDeferOccured | TooBig | io.StartTxDone
|
||||
| StateJam & NibCntEq7 & (~ColWindow | RetryMax)){
|
||||
RetryCnt := 0.U
|
||||
}.elsewhen(StateJam & NibCntEq7 & ColWindow & (RandomEq0 | io.NoBckof) | StateBackOff & RandomEqByteCnt){
|
||||
RetryCnt := RetryCnt + 1.U
|
||||
}
|
||||
|
||||
RetryMax := RetryCnt === io.MaxRet
|
||||
|
||||
when( true.B ){
|
||||
MTxD := // Transmit nibble
|
||||
Mux(
|
||||
StateData(0), io.TxData(3,0), // Lower nibble
|
||||
Mux(StateData(1), io.TxData(7,4), // Higher nibble
|
||||
Mux( StateFCS, Cat(~Crc.extract(28), ~Crc.extract(29), ~Crc.extract(30), ~Crc.extract(31)), // Crc
|
||||
Mux(StateJam, 9.U, // Jam pattern
|
||||
Mux(
|
||||
StatePreamble, Mux(NibCntEq15, "hd".U, 5.U),// SFD,Preamble
|
||||
0.U
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val PacketFinished_d = io.StartTxDone | TooBig | io.LateCollision | io.MaxCollisionOccured | ExcessiveDeferOccured;
|
||||
val PacketFinished = RegNext(PacketFinished_d, false.B)
|
||||
when(true.B){
|
||||
PacketFinished_q := PacketFinished
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
34
src/main/scala/Switch/Parameters.scala
Normal file
34
src/main/scala/Switch/Parameters.scala
Normal file
@@ -0,0 +1,34 @@
|
||||
package Switch
|
||||
|
||||
import chisel3._
|
||||
import chisel3.stage._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
|
||||
import org.chipsalliance.cde.config._
|
||||
|
||||
abstract class SwitchModule(implicit val p: Parameters) extends Module with HasSwitchParameters { def io: Record }
|
||||
abstract class SwitchBundle(implicit val p: Parameters) extends Bundle with HasSwitchParameters
|
||||
|
||||
|
||||
case object SwitchParamsKey extends Field[SwitchSetting]
|
||||
|
||||
|
||||
case class SwitchSetting(
|
||||
// isTileLink: Boolean = true
|
||||
chn: Int = 1
|
||||
){
|
||||
|
||||
}
|
||||
|
||||
trait HasSwitchParameters {
|
||||
implicit val p: Parameters
|
||||
|
||||
val switchSetting = p(SwitchParamsKey)
|
||||
|
||||
def chn = switchSetting.chn
|
||||
|
||||
}
|
||||
|
||||
class SwitchCfg extends Config((_, _, _) => {
|
||||
case SwitchParamsKey => SwitchSetting()
|
||||
})
|
||||
81
src/main/scala/Switch/Switch.scala
Normal file
81
src/main/scala/Switch/Switch.scala
Normal file
@@ -0,0 +1,81 @@
|
||||
package Switch
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
import MAC._
|
||||
|
||||
import org.chipsalliance.cde.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.interrupts._
|
||||
|
||||
import chisel3.experimental.dataview._
|
||||
|
||||
|
||||
class SwitchIO(implicit p: Parameters) extends SwitchBundle{
|
||||
val mii = Vec( chn, new MII )
|
||||
|
||||
val isLoopBack = Output(Vec( chn, Bool()))
|
||||
val asyncReset = Input(AsyncReset())
|
||||
}
|
||||
|
||||
|
||||
class Switch(implicit p: Parameters) extends LazyModule with HasSwitchParameters{
|
||||
|
||||
|
||||
val ethReg = LazyModule(new MacReg)
|
||||
|
||||
lazy val module = new SwitchImp(this)
|
||||
|
||||
}
|
||||
|
||||
class SwitchImp(outer: Switch)(implicit p: Parameters) extends LazyModuleImp(outer) with HasSwitchParameters{
|
||||
val io = IO(new SwitchIO)
|
||||
|
||||
val mac = ( 0 until chn ).map{ i =>
|
||||
Module(new Mac)
|
||||
}
|
||||
|
||||
( 0 until chn ).map{ i =>
|
||||
mac(i).io.mii <> io.mii(i)
|
||||
mac(i).io.asyncReset := io.asyncReset
|
||||
io.isLoopBack(i) := mac(i).io.isLoopBack
|
||||
}
|
||||
|
||||
outer.ethReg.module.io.asyncReset := io.asyncReset
|
||||
outer.ethReg.module.io.viewAsSupertype(new Mac_Config_Bundle) <> mac(0).io.cfg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
val rxBuff = Module(new RxBuff)
|
||||
|
||||
rxBuff.io.enq <> mac(0).io.rxEnq
|
||||
rxBuff.io.deq.data.ready := false.B
|
||||
rxBuff.io.deq.ctrl.ready := false.B
|
||||
|
||||
val txBuff = Module(new TxBuff)
|
||||
txBuff.io.deq <> mac(0).io.txDeq
|
||||
txBuff.io.enq.ctrl.valid := false.B
|
||||
txBuff.io.enq.data.valid := false.B
|
||||
txBuff.io.enq.data.bits := 0.U
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
43
src/main/scala/Switch/WithSwitch.scala
Normal file
43
src/main/scala/Switch/WithSwitch.scala
Normal file
@@ -0,0 +1,43 @@
|
||||
package Switch
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.subsystem.BaseSubsystem
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import org.chipsalliance.cde.config._
|
||||
|
||||
|
||||
trait WithSwitchMix { this: BaseSubsystem =>
|
||||
|
||||
val switch = LazyModule(new Switch)
|
||||
|
||||
// sbus.coupleFrom("switch_mst") { _ := TLBuffer() := switch0.tlClientNode }
|
||||
// pbus.coupleTo("switch_cfg") { switch0.tlMasterNode := TLFragmenter(pbus) := _ }
|
||||
pbus.coupleTo("switch_cfg") { switch.ethReg.configNode := TLFragmenter(pbus) := _ }
|
||||
|
||||
ibus.fromSync := switch.ethReg.int_node
|
||||
|
||||
}
|
||||
|
||||
|
||||
trait WithSwitchMixModuleImp extends LazyModuleImp {
|
||||
val outer: WithSwitchMix
|
||||
|
||||
val switchIO = IO(new SwitchIO)
|
||||
|
||||
switchIO <> outer.switch.module.io
|
||||
|
||||
println("Warning, did you delete the rocket-chip.jar on top to reflash?")
|
||||
println("Warning, did you delete the rocket-chip.jar on top to reflash?")
|
||||
println("Warning, did you delete the rocket-chip.jar on top to reflash?")
|
||||
println("Warning, did you delete the rocket-chip.jar on top to reflash?")
|
||||
println("Warning, did you delete the rocket-chip.jar on top to reflash?")
|
||||
|
||||
}
|
||||
|
||||
class SwitchConfig() extends Config((site, here, up) => {
|
||||
case SwitchParamsKey => SwitchSetting()
|
||||
})
|
||||
|
||||
|
||||
74
src/main/scala/Switch/mac/AsyncFifo.scala.bk
Normal file
74
src/main/scala/Switch/mac/AsyncFifo.scala.bk
Normal 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)
|
||||
|
||||
|
||||
}
|
||||
853
src/main/scala/Switch/mac/MAC.scala
Normal file
853
src/main/scala/Switch/mac/MAC.scala
Normal 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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
239
src/main/scala/Switch/mac/MII.scala
Normal file
239
src/main/scala/Switch/mac/MII.scala
Normal 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
|
||||
|
||||
}
|
||||
|
||||
|
||||
78
src/main/scala/Switch/mac/MacBundle.scala
Normal file
78
src/main/scala/Switch/mac/MacBundle.scala
Normal 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
|
||||
}
|
||||
|
||||
448
src/main/scala/Switch/mac/MacControl.scala
Normal file
448
src/main/scala/Switch/mac/MacControl.scala
Normal 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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
77
src/main/scala/Switch/mac/MacFifo.scala
Normal file
77
src/main/scala/Switch/mac/MacFifo.scala
Normal 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)
|
||||
}
|
||||
|
||||
}
|
||||
58
src/main/scala/Switch/mac/MacSRAM.scala
Normal file
58
src/main/scala/Switch/mac/MacSRAM.scala
Normal 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))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
180
src/main/scala/Switch/mac/MacStatus.scala
Normal file
180
src/main/scala/Switch/mac/MacStatus.scala
Normal 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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
156
src/main/scala/Switch/mac/MacTileLinkRx.scala
Normal file
156
src/main/scala/Switch/mac/MacTileLinkRx.scala
Normal 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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
123
src/main/scala/Switch/mac/MacTileLinkTx.scala
Normal file
123
src/main/scala/Switch/mac/MacTileLinkTx.scala
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
288
src/main/scala/Switch/mac/MacTilelink.scala
Normal file
288
src/main/scala/Switch/mac/MacTilelink.scala
Normal 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(){
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
108
src/main/scala/Switch/mac/RxBuff.scala
Normal file
108
src/main/scala/Switch/mac/RxBuff.scala
Normal 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)
|
||||
|
||||
}
|
||||
|
||||
61
src/main/scala/Switch/mac/TxBuff.scala
Normal file
61
src/main/scala/Switch/mac/TxBuff.scala
Normal 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
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user