2023-06-18 08:34:44 +00:00
package MAC
import chisel3._
2023-06-20 18:26:59 +08:00
import chisel3.util._
2023-06-18 08:34:44 +00:00
2023-07-03 23:51:01 +08:00
trait MDIO { this : Bundle =>
2023-06-18 13:06:31 +00:00
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
}
2023-07-03 23:51:01 +08:00
class MIIMIO extends Bundle with MDIO {
2023-06-20 18:26:59 +08:00
val Divider = Input ( UInt ( 8. W ) ) // Divider for the host clock // Divider (input clock will be divided by the Divider[7:0])
2023-06-18 13:06:31 +00:00
val NoPre = Input ( Bool ( ) ) // No Preamble (no 32-bit preamble)
2023-06-20 18:26:59 +08:00
2023-06-18 13:06:31 +00:00
val WCtrlData = Input ( Bool ( ) ) // Write Control Data operation
2023-06-20 18:26:59 +08:00
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)
2023-06-18 13:06:31 +00:00
val RStat = Input ( Bool ( ) ) // Read Status operation
2023-06-20 18:26:59 +08:00
2023-06-18 13:06:31 +00:00
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)
2023-06-20 18:26:59 +08:00
2023-06-18 13:06:31 +00:00
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 )
2023-06-20 18:26:59 +08:00
val ByteSelect = Wire ( Vec ( 4 , Bool ( ) ) ) // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register.
2023-06-18 13:06:31 +00:00
// Counter counts half period
val Counter = RegInit ( 1. U ( 8. W ) )
2023-06-20 18:26:59 +08:00
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
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
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
2023-06-18 13:06:31 +00:00
Counter : = CounterPreset
} . otherwise {
Counter : = Counter - 1. U
}
}
trait MIIMShiftReg { this : MIIMBase =>
2023-06-20 18:26:59 +08:00
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 ( _ | _ ) ) {
2023-06-18 13:06:31 +00:00
ShiftReg : = Mux1H ( Seq (
2023-06-20 18:26:59 +08:00
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 ) ,
2023-06-18 13:06:31 +00:00
) )
} . otherwise {
2023-06-20 18:26:59 +08:00
ShiftReg : = Cat ( ShiftReg ( 6 , 0 ) , io . mdi )
when ( LatchByte0 ) {
Prsd : = Cat ( Prsd ( 15 , 8 ) , ShiftReg ( 6 , 0 ) , io . mdi )
when ( io . Rgad === 1. U ) {
2023-06-18 13:06:31 +00:00
LinkFail : = ~ ShiftReg . extract ( 1 ) // this is bit [2], because it is not shifted yet
}
2023-06-20 18:26:59 +08:00
} . elsewhen ( LatchByte1 ) {
Prsd : = Cat ( ShiftReg ( 6 , 0 ) , io . mdi , Prsd ( 7 , 0 ) )
2023-06-18 13:06:31 +00:00
}
}
}
}
trait MIIMOutputCtl { this : MIIMBase =>
2023-06-20 18:26:59 +08:00
// 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 ) ) )
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
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
2023-06-18 13:06:31 +00:00
}
2023-06-20 18:26:59 +08:00
class MIIM extends MIIMBase with MIIMClockGen with MIIMShiftReg with MIIMOutputCtl {
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
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
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
// Generation of the Operation signals
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
val StartOp = Wire ( Bool ( ) ) // Start Operation (start of any of the preceding operations)
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
when ( EndBusy ) {
WCtrlDataStart : = false . B
} . elsewhen ( WCtrlData_q ( 1 ) & ~ WCtrlData_q ( 2 ) ) {
WCtrlDataStart : = true . B
}
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
// 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
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
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
2023-06-18 13:06:31 +00:00
when ( EndBusy ) {
RStatStart : = false . B
2023-06-20 18:26:59 +08:00
} . elsewhen ( RStat_q ( 1 ) & ~ RStat_q ( 2 ) ) {
RStatStart : = true . B
2023-06-18 13:06:31 +00:00
}
2023-06-20 18:26:59 +08:00
when ( mdcEn ) {
when ( StartOp ) {
InProgress : = true . B
} . elsewhen ( EndOp ) {
InProgress : = false . B
}
2023-06-18 13:06:31 +00:00
}
2023-06-20 18:26:59 +08:00
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)
2023-06-18 08:34:44 +00:00
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
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
}
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
when ( mdcEn ) {
2023-06-18 13:06:31 +00:00
when ( StartOp ) {
when ( ~ InProgress ) {
2023-06-20 18:26:59 +08:00
WriteOp : = Mux ( WriteDataOp , true . B , false . B )
2023-06-18 13:06:31 +00:00
}
} . elsewhen ( EndOp ) {
WriteOp : = false . B
}
}
2023-06-20 18:26:59 +08:00
when ( mdcEn ) {
2023-06-18 13:06:31 +00:00
when ( InProgress ) {
2023-06-20 18:26:59 +08:00
when ( io . NoPre & BitCounter === 0. U ) {
2023-06-18 13:06:31 +00:00
BitCounter : = "h21" . U
} . otherwise {
BitCounter : = BitCounter + 1. U
}
} . otherwise {
BitCounter : = 0. U
}
2023-06-18 08:34:44 +00:00
}
2023-06-18 13:06:31 +00:00
2023-06-20 18:26:59 +08:00
StartOp : = WriteDataOp | ReadStatusOp | ScanStatusOp
io . Busy : = io . WCtrlData | WCtrlDataStart | io . RStat | RStatStart | SyncStatmdcEn | EndBusy | InProgress | InProgress_q ( 2 ) | Nvalid
}
2023-06-18 13:06:31 +00:00