finish macrx
This commit is contained in:
@@ -1,6 +1,379 @@
|
||||
package MAC
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util
|
||||
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{
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import chisel3.stage._
|
||||
object testModule extends App {
|
||||
(new chisel3.stage.ChiselStage).execute( Array("--target-dir", "generated/", "-e", "verilog" ) ++ args, Seq(
|
||||
ChiselGeneratorAnnotation(() => {
|
||||
new MIIM()
|
||||
new MacRx()
|
||||
})
|
||||
))
|
||||
}
|
||||
Reference in New Issue
Block a user