2023-06-28 23:43:03 +08:00
package MAC
import chisel3._
import chisel3.util._
2023-07-03 16:25:41 +08:00
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy._
2023-07-04 15:40:51 +08:00
import org.chipsalliance.cde.config._
2023-07-03 16:25:41 +08:00
2023-06-28 23:43:03 +08:00
2023-07-04 14:26:24 +08:00
2023-06-29 23:28:05 +08:00
2023-06-30 20:21:03 +08:00
2023-07-11 17:45:32 +08:00
abstract class MacTileLinkBase ( edgeIn : TLEdgeIn , edgeOut : TLEdgeOut ) extends Module {
2023-07-04 15:40:51 +08:00
class MacTileLinkSlaveIO extends Bundle {
2023-07-11 17:38:18 +08:00
val A = Flipped ( Decoupled ( new TLBundleA ( edgeIn . bundle ) ) )
val D = Decoupled ( new TLBundleD ( edgeIn . bundle ) )
2023-07-04 15:40:51 +08:00
}
2023-07-07 21:43:06 +08:00
class MacTileLinkMasterIO extends Bundle {
val A = Decoupled ( new TLBundleA ( edgeOut . bundle ) )
val D = Flipped ( Decoupled ( new TLBundleD ( edgeOut . bundle ) ) )
}
2023-07-03 16:25:41 +08:00
2023-07-11 17:45:32 +08:00
class MacTileLinkIO extends Bundle {
2023-07-03 16:25:41 +08:00
2023-07-11 17:38:18 +08:00
val tlSlv = new MacTileLinkSlaveIO
val tlMst = new MacTileLinkMasterIO
2023-07-03 16:25:41 +08:00
// Rx Status signals
val InvalidSymbol = Input ( Bool ( ) ) // Invalid symbol was received during reception in 100 Mbps mode
val LatchedCrcError = Input ( Bool ( ) ) // CRC error
val RxLateCollision = Input ( Bool ( ) ) // Late collision occured while receiving frame
val ShortFrame = Input ( Bool ( ) ) // Frame shorter then the minimum size (r_MinFL) was received while small packets are enabled (r_RecSmall)
val DribbleNibble = Input ( Bool ( ) ) // Extra nibble received
val ReceivedPacketTooBig = Input ( Bool ( ) ) // Received packet is bigger than r_MaxFL
val ReceivedPacketGood = Input ( Bool ( ) ) // Received packet's length and CRC are good
val AddressMiss = Input ( Bool ( ) ) // When a packet is received AddressMiss status is written to the Rx BD
2023-07-20 10:35:56 +08:00
val r_RxFlow = Input ( Bool ( ) )
val r_PassAll = Input ( Bool ( ) )
2023-07-03 16:25:41 +08:00
val ReceivedPauseFrm = 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
// Tx
val MTxClk = Input ( Bool ( ) ) // Transmit clock (from PHY)
val TxUsedData = Input ( Bool ( ) ) // Transmit packet used data
2023-10-08 11:34:36 +08:00
val TxUnderRun = Input ( Bool ( ) ) // Transmit packet under-run
2023-07-03 16:25:41 +08:00
val PerPacketCrcEn = Output ( Bool ( ) ) // Per packet crc enable
val PerPacketPad = Output ( Bool ( ) ) // Per packet pading
// Rx
val MRxClk = Input ( Bool ( ) ) // Receive clock (from PHY)
val RxStatusWriteLatched_sync2 = Output ( Bool ( ) )
2023-07-20 10:35:56 +08:00
//Register
val r_TxEn = Input ( Bool ( ) ) // Transmit enable
val r_RxEn = Input ( Bool ( ) ) // Receive enable
val r_TxBDNum = Input ( UInt ( 8. W ) ) // Receive buffer descriptor number
// Interrupts
val TxB_IRQ = Output ( Bool ( ) )
val TxE_IRQ = Output ( Bool ( ) )
val RxB_IRQ = Output ( Bool ( ) )
val RxE_IRQ = Output ( Bool ( ) )
val Busy_IRQ = Output ( Bool ( ) )
2023-09-25 14:18:27 +08:00
val asyncReset = Input ( AsyncReset ( ) )
2023-10-08 11:34:36 +08:00
val BlockingTxStatusWrite = Output ( Bool ( ) )
val TxStartFrm_wb = Output ( Bool ( ) )
val ReadTxDataFromFifo_sync = Input ( Bool ( ) )
val TxStartFrm_syncb = Input ( Bool ( ) )
val TxUnderRun_wb = Output ( Bool ( ) )
val TxData_wb = Output ( UInt ( 32. W ) )
val TxValidBytesLatched = Output ( UInt ( 2. W ) )
val TxEndFrm_wb = Output ( Bool ( ) )
val TxRetrySync = Input ( Bool ( ) )
val TxAbortSync = Input ( Bool ( ) ) // Transmit packet abort
val TxDoneSync = Input ( Bool ( ) ) // Transmission ended
2023-10-08 15:13:35 +08:00
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 SyncRxStartFrmSync = Input ( Bool ( ) )
val Busy_IRQ_sync = Input ( Bool ( ) )
val RxReady = Output ( Bool ( ) )
val RxStatusIn = Output ( UInt ( 9. W ) )
2023-07-03 16:25:41 +08:00
}
2023-07-04 15:40:51 +08:00
val io = IO ( new MacTileLinkIO )
2023-06-30 20:21:03 +08:00
2023-07-11 17:38:18 +08:00
val ( _ , _ , isLastD , transDCnt ) = edgeOut . count ( io . tlMst . D )
2023-06-28 23:43:03 +08:00
2023-06-30 20:21:03 +08:00
val BDCs = Wire ( UInt ( 4. W ) )
2023-06-28 23:43:03 +08:00
2023-07-20 10:35:56 +08:00
val TxB_IRQ = RegInit ( false . B ) ; io . TxB_IRQ : = TxB_IRQ
val TxE_IRQ = RegInit ( false . B ) ; io . TxE_IRQ : = TxE_IRQ
val RxB_IRQ = RegInit ( false . B ) ; io . RxB_IRQ : = RxB_IRQ
val RxE_IRQ = RegInit ( false . B ) ; io . RxE_IRQ : = RxE_IRQ
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
2023-10-08 11:34:36 +08:00
val TxUnderRun_wb = RegInit ( false . B ) ; io . TxUnderRun_wb : = TxUnderRun_wb
2023-06-28 23:43:03 +08:00
val TxBDRead = RegInit ( true . B )
val TxStatusWrite = Wire ( Bool ( ) )
2023-06-29 18:29:54 +08:00
val TxLength = RegInit ( 0. U ( 16. W ) )
val LatchedTxLength = RegInit ( 0. U ( 16. W ) )
val TxStatus = RegInit ( 0. U ( 4. W ) ) //[14:11]
val RxStatus = RegInit ( 0. U ( 2. W ) ) //[14:13]
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
2023-06-28 23:43:03 +08:00
2023-10-08 11:34:36 +08:00
val TxStartFrm_wb = RegInit ( false . B ) ; io . TxStartFrm_wb : = TxStartFrm_wb
2023-06-30 16:00:02 +08:00
2023-09-26 21:41:19 +08:00
// Signals used for various purposes
2023-10-08 11:34:36 +08:00
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 )
2023-09-26 21:41:19 +08:00
2023-06-28 23:43:03 +08:00
val TxRetryPacket = RegInit ( false . B )
val TxRetryPacket_NotCleared = RegInit ( false . B )
val TxDonePacket = RegInit ( false . B )
val TxDonePacket_NotCleared = RegInit ( false . B )
2023-06-29 18:29:54 +08:00
val TxAbortPacket = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
val TxAbortPacket_NotCleared = RegInit ( false . B )
val RxBDReady = RegInit ( false . B )
2023-10-08 15:13:35 +08:00
val RxReady = RegInit ( false . B ) ; io . RxReady : = RxReady
2023-06-28 23:43:03 +08:00
val TxBDReady = RegInit ( false . B )
val RxBDRead = RegInit ( false . B )
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
2023-10-08 11:34:36 +08:00
val BlockingTxStatusWrite = RegInit ( false . B ) ; io . BlockingTxStatusWrite : = BlockingTxStatusWrite
2023-06-28 23:43:03 +08:00
val BlockingTxBDRead = RegInit ( false . B )
val RxBDAddress = RegInit ( 0. U ( 7. W ) ) //[7:1]
val TxBDAddress = RegInit ( 0. U ( 7. W ) ) //[7:1]
val ShiftEnded = RegInit ( false . B )
val RxOverrun = RegInit ( false . B )
val BDWrite = RegInit ( 0. U ( 4. W ) ) // BD Write Enable for access from WISHBONE side
val BDRead = RegInit ( false . B ) // BD Read access from WISHBONE side
val RxBDDataIn = Wire ( UInt ( 32. W ) ) // Rx BD data in
val TxBDDataIn = Wire ( UInt ( 32. W ) ) // Tx BD data in
2023-10-08 11:34:36 +08:00
val TxEndFrm_wb = RegInit ( false . B ) ; io . TxEndFrm_wb : = TxEndFrm_wb
2023-06-28 23:43:03 +08:00
2023-09-26 21:41:19 +08:00
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
2023-06-28 23:43:03 +08:00
val RxStatusWrite = Wire ( Bool ( ) )
val RxBufferFull = Wire ( Bool ( ) )
val RxBufferAlmostEmpty = Wire ( Bool ( ) )
val RxBufferEmpty = Wire ( Bool ( ) )
2023-06-30 20:21:03 +08:00
val BDAck = Reg ( Bool ( ) ) ;
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
// Delayed stage signals
2023-09-26 21:41:19 +08:00
// val WbEn = RegInit(true.B)
// val WbEn_q = RegNext(WbEn, false.B)
// val RxEn = RegInit(false.B)
// val RxEn_q = RegNext(RxEn, false.B)
// val TxEn = RegInit(false.B)
// val TxEn_q = RegNext(TxEn, false.B)
2023-07-20 10:35:56 +08:00
val r_TxEn_q = RegNext ( io . r_TxEn , false . B )
val r_RxEn_q = RegNext ( io . r_RxEn , false . B )
2023-06-28 23:43:03 +08:00
2023-09-26 21:41:19 +08:00
def StateIdle = 0. U ( 3. W )
def StateWB = 1. U ( 3. W )
def StateTX = 2. U ( 3. W )
def StateRX = 3. U ( 3. W )
val stateNxt = RegInit ( StateWB )
val stateCur = RegNext ( stateNxt , StateIdle )
2023-06-28 23:43:03 +08:00
val ram_ce = true . B
val ram_we = Wire ( UInt ( 4. W ) )
val ram_oe = Wire ( Bool ( ) )
val ram_addr = RegInit ( 0. U ( 8. W ) )
val ram_di = RegInit ( 0. U ( 32. W ) )
val ram_do = Wire ( UInt ( 32. W ) )
2023-06-29 23:28:05 +08:00
val txBuffDesc = ram_do . asTypeOf ( new TxBuffDesc )
val rxBuffDesc = ram_do . asTypeOf ( new RxBuffDesc )
2023-06-28 23:43:03 +08:00
2023-06-30 14:46:23 +08:00
2023-06-28 23:43:03 +08:00
val TxPointerRead = RegInit ( false . B )
val TxEn_needed = RegInit ( false . B )
val RxEn_needed = RegInit ( false . B )
2023-06-29 18:29:54 +08:00
val RxPointerRead = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
// RX shift ending signals
val ShiftEndedSync3 = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-10-08 15:13:35 +08:00
2023-06-28 23:43:03 +08:00
2023-07-04 15:40:51 +08:00
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val StartOccured = RegInit ( false . B )
2023-10-07 16:44:13 +08:00
2023-06-29 18:29:54 +08:00
val TxFifoClear = Wire ( Bool ( ) )
val TxBufferAlmostFull = Wire ( Bool ( ) )
val TxBufferFull = Wire ( Bool ( ) )
val TxBufferEmpty = Wire ( Bool ( ) )
val TxBufferAlmostEmpty = Wire ( Bool ( ) )
val BlockReadTxDataFromMemory = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val ReadTxDataFromFifo_wb = Wire ( Bool ( ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val txfifo_cnt = Wire ( UInt ( 5. W ) )
val rxfifo_cnt = Wire ( UInt ( 5. W ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val ReadTxDataFromMemory = RegInit ( false . B )
val WriteRxDataToMemory = Wire ( Bool ( ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val MasterWbTX = RegInit ( false . B )
val MasterWbRX = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val TxPointerMSB = RegInit ( 0. U ( 30. W ) ) //[31:2]
val RxPointerMSB = RegInit ( 0. U ( 30. W ) ) //[31:2]
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val cyc_cleared = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-07-07 21:43:06 +08:00
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
2023-06-28 23:43:03 +08:00
2023-10-08 15:13:35 +08:00
val RxAbortPluse = io . RxAbortSync & RegNext ( io . RxAbortSync , false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val RxStatusWriteLatched = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-06-30 16:14:58 +08:00
val RxStatusWriteLatched_syncb = ShiftRegister ( io . RxStatusWriteLatched_sync2 , 2 , false . B , true . B )
2023-10-08 15:13:35 +08:00
io . RxStatusWriteLatched_sync2 : = ShiftRegister ( RxStatusWriteLatched , 2 , false . B , true . B )
2023-06-28 23:43:03 +08:00
2023-07-07 21:43:06 +08:00
2023-06-29 18:29:54 +08:00
when ( true . B ) {
2023-09-26 21:41:19 +08:00
BDAck : = stateNxt === StateWB & Mux ( stateCur === StateWB , BDWrite . orR , BDRead )
2023-06-29 18:29:54 +08:00
}
2023-06-28 23:43:03 +08:00
// Generic synchronous single-port RAM interface
2023-06-29 18:29:54 +08:00
val bd_ram = Module ( new MacSRAM )
2023-06-28 23:43:03 +08:00
2023-06-30 20:21:03 +08:00
val BD_WB_DAT_O = ram_do
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
bd_ram . io . ce : = ram_ce
bd_ram . io . we : = ram_we . asBools
bd_ram . io . oe : = ram_oe
bd_ram . io . addr : = ram_addr
bd_ram . io . di : = ram_di
ram_do : = bd_ram . io . dato
2023-06-28 23:43:03 +08:00
ram_we : =
2023-09-26 21:41:19 +08:00
( Fill ( 4 , ( stateNxt === StateWB & stateCur === StateWB ) ) & BDWrite ) |
( Fill ( 4 , ( TxStatusWrite | RxStatusWrite ) ) )
2023-06-28 23:43:03 +08:00
ram_oe : =
2023-09-26 21:41:19 +08:00
( BDRead & ( stateNxt === StateWB ) & ( stateCur === StateWB ) ) |
( ( TxBDRead | TxPointerRead ) & ( stateNxt === StateTX ) & ( stateCur === StateTX ) ) |
( ( RxBDRead | RxPointerRead ) & ( stateNxt === StateRX ) & ( stateCur === StateRX ) )
2023-06-28 23:43:03 +08:00
2023-09-26 21:41:19 +08:00
when ( ~ TxBDReady & io . r_TxEn & stateNxt === StateWB & stateCur =/= StateWB ) {
2023-06-28 23:43:03 +08:00
TxEn_needed : = true . B
2023-09-26 21:41:19 +08:00
} . elsewhen ( TxPointerRead & stateNxt === StateTX & stateCur === StateTX ) {
2023-06-28 23:43:03 +08:00
TxEn_needed : = false . B
}
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
// Enabling access to the RAM for three devices.
2023-06-29 18:29:54 +08:00
// Switching between three stages depends on enable signals
2023-09-26 21:41:19 +08:00
switch ( stateCur ) {
is ( StateIdle ) {
when ( RxEn_needed === false . B & TxEn_needed === false . B ) {
stateNxt : = StateWB // Idle state. We go to WbEn access stage.
ram_addr : = io . tlSlv . A . bits . address ( 9 , 2 ) // [11:2 ] -> [9:2]
ram_di : = io . tlSlv . A . bits . data
BDWrite : = BDCs & Fill ( 4 , ( io . tlSlv . A . bits . opcode === 0. U ) || ( io . tlSlv . A . bits . opcode === 1. U ) )
BDRead : = BDCs . orR & ( io . tlSlv . A . bits . opcode === 4. U )
}
}
is ( StateWB ) {
when ( RxEn_needed ) { // synopsys parallel_case
stateNxt : = StateRX // wb access stage and r_RxEn is enabled
ram_addr : = Cat ( RxBDAddress , RxPointerRead )
ram_di : = RxBDDataIn
} . elsewhen ( TxEn_needed ) {
stateNxt : = StateTX // wb access stage, r_RxEn is disabled but r_TxEn is enabled
ram_addr : = Cat ( TxBDAddress , TxPointerRead ) //[7,1] + [0]
ram_di : = TxBDDataIn
} . otherwise {
stateNxt : = StateIdle // WbEn access stage and there is no need for other stages. WbEn needs to be switched off for a bit
}
}
is ( StateRX ) {
when ( TxEn_needed ) {
stateNxt : = StateTX // RxEn access stage and r_TxEn is enabled
ram_addr : = Cat ( TxBDAddress , TxPointerRead )
ram_di : = TxBDDataIn
} . otherwise {
stateNxt : = StateWB // RxEn access stage and r_TxEn is disabled
ram_addr : = io . tlSlv . A . bits . address ( 9 , 2 ) // [11:2 ] -> [9:2];
ram_di : = io . tlSlv . A . bits . data
BDWrite : = BDCs & Fill ( 4 , ( io . tlSlv . A . bits . opcode === 0. U ) || ( io . tlSlv . A . bits . opcode === 1. U ) )
BDRead : = BDCs . orR & ( io . tlSlv . A . bits . opcode === 4. U )
}
}
is ( StateTX ) {
when ( true . B ) {
stateNxt : = StateWB // TxEn access stage (we always go to wb access stage)
ram_addr : = io . tlSlv . A . bits . address ( 9 , 2 ) //[11:2 ] ->[9:2]
ram_di : = io . tlSlv . A . bits . data
BDWrite : = BDCs & Fill ( 4 , ( io . tlSlv . A . bits . opcode === 0. U ) || ( io . tlSlv . A . bits . opcode === 1. U ) )
BDRead : = BDCs . orR & ( io . tlSlv . A . bits . opcode === 4. U )
}
}
2023-06-29 18:29:54 +08:00
}
2023-09-26 21:41:19 +08:00
2023-06-30 16:00:02 +08:00
val ResetTxBDReady = TxDonePulse | TxAbortPulse | TxRetryPulse
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
// Latching READY status of the Tx buffer descriptor
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateTX & stateCur === StateTX & TxBDRead ) { // TxBDReady is sampled only once at the beginning.
2023-06-29 23:28:05 +08:00
TxBDReady : = txBuffDesc . rd & ( txBuffDesc . len > 4. U )
2023-06-28 23:43:03 +08:00
} . elsewhen ( ResetTxBDReady ) { // Only packets larger then 4 bytes are transmitted.
TxBDReady : = false . B
}
2023-06-30 14:46:23 +08:00
val StartTxBDRead = ( TxRetryPacket_NotCleared | TxStatusWrite ) & ~ BlockingTxBDRead & ~ TxBDReady // Reading the Tx buffer descriptor
2023-06-28 23:43:03 +08:00
when ( StartTxBDRead ) {
TxBDRead : = true . B
} . elsewhen ( TxBDReady ) {
TxBDRead : = false . B
}
2023-06-30 14:46:23 +08:00
val StartTxPointerRead = TxBDRead & TxBDReady // Reading Tx BD pointer
2023-06-28 23:43:03 +08:00
// Reading Tx BD Pointer
when ( StartTxPointerRead ) {
TxPointerRead : = true . B
2023-09-26 21:41:19 +08:00
} . elsewhen ( stateCur === StateTX ) {
2023-06-28 23:43:03 +08:00
TxPointerRead : = false . B
}
// Writing status back to the Tx buffer descriptor
2023-09-26 21:41:19 +08:00
TxStatusWrite : = ( TxDonePacket_NotCleared | TxAbortPacket_NotCleared ) & stateNxt === StateTX & stateCur === StateTX & ~ BlockingTxStatusWrite
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
// Status writing must occur only once. Meanwhile it is blocked.
2023-10-08 11:34:36 +08:00
when ( ~ io . TxDoneSync & ~ io . TxAbortSync ) {
2023-06-28 23:43:03 +08:00
BlockingTxStatusWrite : = false . B
} . elsewhen ( TxStatusWrite ) {
BlockingTxStatusWrite : = true . B
}
2023-09-28 18:45:14 +08:00
2023-06-28 23:43:03 +08:00
// TxBDRead state is activated only once.
when ( StartTxBDRead ) {
BlockingTxBDRead : = true . B
} . elsewhen ( ~ StartTxBDRead & ~ TxBDReady ) {
BlockingTxBDRead : = false . B
}
2023-06-30 16:00:02 +08:00
// Latching status from the tx buffer descriptor Data is avaliable one cycle after the access is started (at that time signal TxEn is not active)
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateTX & stateCur === StateTX & TxBDRead ) {
2023-06-29 23:28:05 +08:00
TxStatus : = Cat ( txBuffDesc . irq , txBuffDesc . wr , txBuffDesc . pad , txBuffDesc . crc )
2023-06-28 23:43:03 +08:00
}
//Latching length from the buffer descriptor;
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateTX & stateCur === StateTX & TxBDRead ) {
2023-06-29 23:28:05 +08:00
TxLength : = txBuffDesc . len
2023-07-07 21:43:06 +08:00
}
2023-07-11 17:38:18 +08:00
. elsewhen ( MasterWbTX & io . tlMst . D . fire ) { //tx tileRead
2023-06-30 14:46:23 +08:00
when ( TxLength < 4. U ) {
2023-06-28 23:43:03 +08:00
TxLength : = 0. U
2023-09-27 16:31:56 +08:00
} . otherwise {
2023-06-28 23:43:03 +08:00
TxLength : = TxLength - 4. U // Length is subtracted at the data request
}
}
2023-07-07 21:43:06 +08:00
2023-06-28 23:43:03 +08:00
//Latching length from the buffer descriptor;
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateTX & stateCur === StateTX & TxBDRead ) {
2023-06-29 23:28:05 +08:00
LatchedTxLength : = txBuffDesc . len
2023-06-28 23:43:03 +08:00
}
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateTX & stateCur === StateTX & TxPointerRead ) {
2023-06-30 14:46:23 +08:00
TxPointerMSB : = ram_do ( 31 , 2 ) // Latching Tx buffer pointer from buffer descriptor. Only 30 MSB bits are latched because TxPointerMSB is only used for word-aligned accesses.
2023-09-27 16:31:56 +08:00
when ( ram_do ( 1 , 0 ) =/= 0. U ) {
printf ( "Warning, force to align at tx ram" )
}
2023-07-11 17:38:18 +08:00
} . elsewhen ( io . tlMst . D . fire & io . tlMst . D . bits . opcode === 1. U ) {
2023-06-28 23:43:03 +08:00
TxPointerMSB : = TxPointerMSB + 1. U // TxPointer is word-aligned
}
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
2023-07-07 21:43:06 +08:00
val isTlMstBusy = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-06-30 14:46:23 +08:00
when ( ( TxLength === 0. U ) | TxAbortPulse | TxRetryPulse ) {
2023-06-28 23:43:03 +08:00
ReadTxDataFromMemory : = false . B
2023-09-26 21:41:19 +08:00
} . elsewhen ( stateNxt === StateTX & stateCur === StateTX & TxPointerRead ) {
2023-06-28 23:43:03 +08:00
ReadTxDataFromMemory : = true . B
}
2023-07-07 21:43:06 +08:00
val ReadTxDataFromMemory_2 = ReadTxDataFromMemory & ~ BlockReadTxDataFromMemory ;
2023-06-28 23:43:03 +08:00
2023-07-07 21:43:06 +08:00
when (
( TxBufferAlmostFull | TxLength <= 4. U ) & MasterWbTX & isTlMstBusy & ( ~ ( TxAbortPacket_NotCleared | TxRetryPacket_NotCleared ) ) ) {
2023-06-28 23:43:03 +08:00
BlockReadTxDataFromMemory : = true . B
} . elsewhen ( ReadTxDataFromFifo_wb | TxDonePacket | TxAbortPacket | TxRetryPacket ) {
BlockReadTxDataFromMemory : = false . B
}
2023-07-07 21:43:06 +08:00
2023-06-28 23:43:03 +08:00
TxFifoClear : = ( TxAbortPacket | TxRetryPacket )
2023-06-29 18:29:54 +08:00
val tx_fifo = Module ( new MacFifo ( dw = 32 , dp = 16 ) )
2023-07-11 17:38:18 +08:00
tx_fifo . io . data_in : = io . tlMst . D . bits . data
tx_fifo . io . write : = io . tlMst . D . fire & io . tlMst . D . bits . opcode === 1. U
2023-07-07 21:43:06 +08:00
2023-06-28 23:43:03 +08:00
tx_fifo . io . read : = ReadTxDataFromFifo_wb & ~ TxBufferEmpty
tx_fifo . io . clear : = TxFifoClear
2023-10-08 11:34:36 +08:00
io . TxData_wb : = tx_fifo . io . data_out
2023-06-28 23:43:03 +08:00
TxBufferFull : = tx_fifo . io . full
TxBufferAlmostFull : = tx_fifo . io . almost_full
TxBufferAlmostEmpty : = tx_fifo . io . almost_empty
TxBufferEmpty : = tx_fifo . io . empty
txfifo_cnt : = tx_fifo . io . cnt
2023-06-30 16:00:02 +08:00
// Start: Generation of the TxStartFrm_wb which is then synchronized to the MTxClk
2023-06-30 14:46:23 +08:00
when ( TxBDReady & ~ StartOccured & ( TxBufferFull | TxLength === 0. U ) ) {
2023-06-28 23:43:03 +08:00
TxStartFrm_wb : = true . B
2023-10-08 11:34:36 +08:00
} . elsewhen ( io . TxStartFrm_syncb ) {
2023-06-28 23:43:03 +08:00
TxStartFrm_wb : = false . B
}
2023-06-30 16:00:02 +08:00
// StartOccured: TxStartFrm_wb occurs only ones at the beginning. Then it's blocked.
2023-06-28 23:43:03 +08:00
when ( TxStartFrm_wb ) {
StartOccured : = true . B
} . elsewhen ( ResetTxBDReady ) {
StartOccured : = false . B
}
// TxEndFrm_wb: indicator of the end of frame
2023-06-30 14:46:23 +08:00
when ( ( TxLength === 0. U ) & TxBufferAlmostEmpty & io . TxUsedData ) {
2023-06-28 23:43:03 +08:00
TxEndFrm_wb : = true . B
} . elsewhen ( TxRetryPulse | TxDonePulse | TxAbortPulse ) {
TxEndFrm_wb : = false . B
}
// Marks which bytes are valid within the word.
2023-06-30 16:00:02 +08:00
val TxValidBytes = Mux ( TxLength < 4. U , TxLength ( 1 , 0 ) , 0. U )
2023-10-08 11:34:36 +08:00
val TxValidBytesLatched = RegInit ( 0. U ( 2. W ) ) ; io . TxValidBytesLatched : = TxValidBytesLatched
2023-09-26 21:41:19 +08:00
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
val LatchValidBytes = ShiftRegisters ( ( TxLength < 4. U ) & TxBDReady , 2 , false . B , true . B )
2023-06-28 23:43:03 +08:00
// Latching valid bytes
2023-06-30 16:00:02 +08:00
when ( LatchValidBytes ( 0 ) & ~ LatchValidBytes ( 1 ) ) {
2023-06-28 23:43:03 +08:00
TxValidBytesLatched : = TxValidBytes
} . elsewhen ( TxRetryPulse | TxDonePulse | TxAbortPulse ) {
TxValidBytesLatched : = 0. U
}
2023-06-29 18:29:54 +08:00
// dontTouch(TxStatus)
2023-06-30 16:00:02 +08:00
val TxIRQEn = TxStatus . extract ( 3 ) //[14:11]
val WrapTxStatusBit = TxStatus . extract ( 2 )
2023-06-29 18:29:54 +08:00
io . PerPacketPad : = TxStatus . extract ( 1 )
io . PerPacketCrcEn : = TxStatus . extract ( 0 )
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
val RxIRQEn = RxStatus . extract ( 1 ) //[14:13]
val WrapRxStatusBit = RxStatus . extract ( 0 )
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
// Temporary Tx and Rx buffer descriptor address//[7:1]
val TempTxBDAddress = Mux ( TxStatusWrite & ~ WrapTxStatusBit , ( TxBDAddress + 1. U ) , 0. U ) // Tx BD increment or wrap (last BD)
2023-07-20 10:35:56 +08:00
val TempRxBDAddress = Mux ( WrapRxStatusBit , io . r_TxBDNum ( 6 , 0 ) , ( RxBDAddress + 1. U ) ) // Using first Rx BD / Using next Rx BD
2023-06-28 23:43:03 +08:00
// Latching Tx buffer descriptor address
2023-07-20 10:35:56 +08:00
when ( io . r_TxEn & ( ~ r_TxEn_q ) ) {
2023-06-28 23:43:03 +08:00
TxBDAddress : = 0. U
} . elsewhen ( TxStatusWrite ) {
TxBDAddress : = TempTxBDAddress
}
// Latching Rx buffer descriptor address
when ( io . r_RxEn & ( ~ r_RxEn_q ) ) {
2023-07-20 10:35:56 +08:00
RxBDAddress : = io . r_TxBDNum ( 6 , 0 )
2023-06-28 23:43:03 +08:00
} . elsewhen ( RxStatusWrite ) {
RxBDAddress : = TempRxBDAddress ;
}
2023-06-29 18:29:54 +08:00
val TxStatusInLatched = Cat ( io . TxUnderRun , io . RetryCntLatched , io . RetryLimit , io . LateCollLatched , io . DeferLatched , io . CarrierSenseLost )
2023-10-08 15:13:35 +08:00
RxBDDataIn : = Cat ( io . LatchedRxLength_rxclk , 0. U ( 1. W ) , RxStatus , 0. U ( 4. W ) , io . RxStatusInLatched_rxclk )
2023-06-28 23:43:03 +08:00
TxBDDataIn : = Cat ( LatchedTxLength , 0. U ( 1. W ) , TxStatus , 0. U ( 2. W ) , TxStatusInLatched )
2023-09-26 21:41:19 +08:00
2023-06-29 18:29:54 +08:00
2023-06-30 16:14:58 +08:00
val TxError = io . TxUnderRun | io . RetryLimit | io . LateCollLatched | io . CarrierSenseLost
2023-06-28 23:43:03 +08:00
val TxAbortPacketBlocked = RegInit ( false . B )
2023-06-30 16:00:02 +08:00
when (
2023-10-08 11:34:36 +08:00
io . TxAbortSync & ( ~ TxAbortPacketBlocked ) & MasterWbTX & io . tlMst . D . fire & isLastD |
io . TxAbortSync & ( ~ TxAbortPacketBlocked ) & ( ~ MasterWbTX ) ) {
2023-06-28 23:43:03 +08:00
TxAbortPacket : = true . B
} . otherwise {
TxAbortPacket : = false . B
}
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateTX & stateCur === StateTX & TxAbortPacket_NotCleared ) {
2023-06-28 23:43:03 +08:00
TxAbortPacket_NotCleared : = false . B
2023-06-30 16:00:02 +08:00
} . elsewhen (
2023-10-08 11:34:36 +08:00
io . TxAbortSync & ( ~ TxAbortPacketBlocked ) & MasterWbTX & io . tlMst . D . fire & isLastD |
io . TxAbortSync & ( ~ TxAbortPacketBlocked ) & ( ~ MasterWbTX ) ) {
2023-06-28 23:43:03 +08:00
TxAbortPacket_NotCleared : = true . B
}
2023-10-08 11:34:36 +08:00
when ( ~ io . TxAbortSync & RegNext ( io . TxAbortSync , false . B ) ) {
2023-06-28 23:43:03 +08:00
TxAbortPacketBlocked : = false . B
} . elsewhen ( TxAbortPacket ) {
TxAbortPacketBlocked : = true . B
}
val TxRetryPacketBlocked = RegInit ( false . B )
when (
2023-10-08 11:34:36 +08:00
io . TxRetrySync & ~ TxRetryPacketBlocked & MasterWbTX & io . tlMst . D . fire & isLastD |
io . TxRetrySync & ~ TxRetryPacketBlocked & ~ MasterWbTX ) {
2023-06-28 23:43:03 +08:00
TxRetryPacket : = true . B
} . otherwise {
TxRetryPacket : = false . B
}
when ( StartTxBDRead ) {
TxRetryPacket_NotCleared : = false . B
} . elsewhen (
2023-10-08 11:34:36 +08:00
io . TxRetrySync & ~ TxRetryPacketBlocked & MasterWbTX & io . tlMst . D . fire & isLastD |
io . TxRetrySync & ~ TxRetryPacketBlocked & ~ MasterWbTX ) {
2023-06-28 23:43:03 +08:00
TxRetryPacket_NotCleared : = true . B
}
2023-10-08 11:34:36 +08:00
when ( ~ io . TxRetrySync & RegNext ( io . TxRetrySync , false . B ) ) {
2023-06-28 23:43:03 +08:00
TxRetryPacketBlocked : = false . B
} . elsewhen ( TxRetryPacket ) {
TxRetryPacketBlocked : = true . B
}
val TxDonePacketBlocked = RegInit ( false . B )
when (
2023-10-08 11:34:36 +08:00
io . TxDoneSync & ~ TxDonePacketBlocked & MasterWbTX & io . tlMst . D . fire & isLastD |
io . TxDoneSync & ~ TxDonePacketBlocked & ~ MasterWbTX ) {
2023-06-28 23:43:03 +08:00
TxDonePacket : = true . B
} . otherwise {
TxDonePacket : = false . B
}
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateTX & stateCur === StateTX & TxDonePacket_NotCleared ) {
2023-06-28 23:43:03 +08:00
TxDonePacket_NotCleared : = false . B
} . elsewhen (
2023-10-08 11:34:36 +08:00
io . TxDoneSync & ~ TxDonePacketBlocked & MasterWbTX & io . tlMst . D . fire & isLastD |
io . TxDoneSync & ~ TxDonePacketBlocked & ~ MasterWbTX ) {
2023-06-28 23:43:03 +08:00
TxDonePacket_NotCleared : = true . B
}
2023-10-08 11:34:36 +08:00
when ( ~ io . TxDoneSync & RegNext ( io . TxDoneSync , false . B ) ) {
2023-06-28 23:43:03 +08:00
TxDonePacketBlocked : = false . B
} . elsewhen ( TxDonePacket ) {
TxDonePacketBlocked : = true . B
}
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
// Tx under run
when ( TxAbortPulse ) {
TxUnderRun_wb : = false . B
} . elsewhen ( TxBufferEmpty & ReadTxDataFromFifo_wb ) {
TxUnderRun_wb : = true . B
}
2023-10-08 11:34:36 +08:00
ReadTxDataFromFifo_wb : = io . ReadTxDataFromFifo_sync & ~ RegNext ( io . ReadTxDataFromFifo_sync , false . B )
2023-06-28 23:43:03 +08:00
2023-10-08 15:13:35 +08:00
val StartRxBDRead = RxStatusWrite | RegNext ( RxAbortPluse , false . B ) | ( io . r_RxEn & ~ r_RxEn_q )
2023-06-28 23:43:03 +08:00
// Reading the Rx buffer descriptor
when ( StartRxBDRead & ~ RxReady ) {
RxBDRead : = true . B
} . elsewhen ( RxBDReady ) {
RxBDRead : = false . B
}
2023-06-30 16:14:58 +08:00
// Reading of the next receive buffer descriptor starts after reception status is written to the previous one.
2023-06-28 23:43:03 +08:00
// Latching READY status of the Rx buffer descriptor
when ( RxPointerRead ) {
RxBDReady : = false . B
2023-09-26 21:41:19 +08:00
} . elsewhen ( stateNxt === StateRX & stateCur === StateRX & RxBDRead ) {
2023-06-30 16:14:58 +08:00
RxBDReady : = rxBuffDesc . e // RxBDReady is sampled only once at the beginning
2023-06-28 23:43:03 +08:00
}
2023-06-30 16:14:58 +08:00
// Latching Rx buffer descriptor status Data is avaliable one cycle after the access is started (at that time signal RxEn is not active)
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateRX & stateCur === StateRX & RxBDRead ) {
2023-06-29 23:28:05 +08:00
RxStatus : = Cat ( rxBuffDesc . irq , rxBuffDesc . wrap )
2023-06-28 23:43:03 +08:00
}
// RxReady generation
2023-10-08 15:13:35 +08:00
when ( ShiftEnded | RxAbortPluse | ~ io . r_RxEn & r_RxEn_q ) {
2023-06-28 23:43:03 +08:00
RxReady : = false . B
2023-09-26 21:41:19 +08:00
} . elsewhen ( stateNxt === StateRX & stateCur === StateRX & RxPointerRead ) {
2023-06-28 23:43:03 +08:00
RxReady : = true . B
}
// Reading Rx BD pointer
2023-06-30 16:14:58 +08:00
val StartRxPointerRead = RxBDRead & RxBDReady
2023-06-28 23:43:03 +08:00
// Reading Tx BD Pointer
when ( StartRxPointerRead ) {
RxPointerRead : = true . B
2023-09-26 21:41:19 +08:00
} . elsewhen ( stateNxt === StateRX & stateCur === StateRX ) {
2023-06-28 23:43:03 +08:00
RxPointerRead : = false . B
}
//Latching Rx buffer pointer from buffer descriptor;
2023-09-26 21:41:19 +08:00
when ( stateNxt === StateRX & stateCur === StateRX & RxPointerRead ) {
2023-06-28 23:43:03 +08:00
RxPointerMSB : = ram_do ( 31 , 2 )
2023-07-11 17:38:18 +08:00
} . elsewhen ( MasterWbRX & io . tlMst . A . fire ) {
2023-06-28 23:43:03 +08:00
RxPointerMSB : = RxPointerMSB + 1. U // Word access (always word access. m_wb_sel_o are used for selecting bytes)
}
2023-09-26 21:41:19 +08:00
when ( ~ RxReady & io . r_RxEn & stateNxt === StateWB & stateCur =/= StateWB ) {
2023-06-28 23:43:03 +08:00
RxEn_needed : = true . B
2023-09-26 21:41:19 +08:00
} . elsewhen ( RxPointerRead & stateNxt === StateRX & stateCur === StateRX ) {
2023-06-28 23:43:03 +08:00
RxEn_needed : = false . B
}
// Reception status is written back to the buffer descriptor after the end of frame is detected.
2023-09-26 21:41:19 +08:00
RxStatusWrite : = ShiftEnded & stateNxt === StateRX & stateCur === StateRX
2023-06-28 23:43:03 +08:00
2023-10-08 15:13:35 +08:00
val WriteRxDataToFifo_wb = io . WriteRxDataToFifoSync & ~ RegNext ( io . WriteRxDataToFifoSync , false . B )
val RxFifoReset = io . SyncRxStartFrmSync & ~ RegNext ( io . SyncRxStartFrmSync , false . B )
2023-06-29 18:29:54 +08:00
val rx_fifo = Module ( new MacFifo ( dw = 32 , dp = 16 ) )
2023-10-08 15:13:35 +08:00
rx_fifo . io . data_in : = io . RxDataLatched2_rxclk
2023-06-29 18:29:54 +08:00
rx_fifo . io . write : = WriteRxDataToFifo_wb & ~ RxBufferFull
2023-07-11 17:38:18 +08:00
rx_fifo . io . read : = MasterWbRX & io . tlMst . A . fire
2023-06-29 18:29:54 +08:00
rx_fifo . io . clear : = RxFifoReset
2023-07-07 21:43:06 +08:00
2023-06-29 18:29:54 +08:00
RxBufferFull : = rx_fifo . io . full
RxBufferAlmostEmpty : = rx_fifo . io . almost_empty
RxBufferEmpty : = rx_fifo . io . empty
rxfifo_cnt : = rx_fifo . io . cnt
2023-07-07 21:43:06 +08:00
2023-06-29 18:29:54 +08:00
WriteRxDataToMemory : = ~ RxBufferEmpty
2023-07-07 21:43:06 +08:00
2023-06-29 18:29:54 +08:00
2023-10-08 15:13:35 +08:00
when ( io . ShiftEndedSync & ~ RegNext ( io . ShiftEndedSync , false . B ) ) {
2023-06-29 18:29:54 +08:00
ShiftEndedSync3 : = true . B
} . elsewhen ( ShiftEnded ) {
ShiftEndedSync3 : = false . B
}
// Generation of the end-of-frame signal
2023-07-11 17:38:18 +08:00
when ( ShiftEndedSync3 & MasterWbRX & io . tlMst . A . fire & RxBufferAlmostEmpty & ~ ShiftEnded ) {
2023-06-29 18:29:54 +08:00
ShiftEnded : = true . B
} . elsewhen ( RxStatusWrite ) {
ShiftEnded : = false . B
}
2023-10-08 15:13:35 +08:00
io . RxStatusIn : = Cat ( io . ReceivedPauseFrm , io . AddressMiss , RxOverrun , io . InvalidSymbol , io . DribbleNibble , io . ReceivedPacketTooBig , io . ShortFrame , io . LatchedCrcError , io . RxLateCollision )
2023-06-29 18:29:54 +08:00
// Rx overrun
when ( RxStatusWrite ) {
RxOverrun : = false . B
} . elsewhen ( RxBufferFull & WriteRxDataToFifo_wb ) {
RxOverrun : = true . B
}
// ShortFrame (RxStatusInLatched[2]) can not set an error because short frames are aborted when signal r_RecSmall is set to 0 in MODER register.
// AddressMiss is identifying that a frame was received because of the promiscous mode and is not an error
2023-10-08 15:13:35 +08:00
val RxError = ( io . RxStatusInLatched_rxclk ( 6 , 3 ) . orR ) | ( io . RxStatusInLatched_rxclk ( 1 , 0 ) . orR )
2023-06-29 18:29:54 +08:00
// Latching and synchronizing RxStatusWrite signal. This signal is used for clearing the ReceivedPauseFrm signal
2023-06-30 16:14:58 +08:00
when ( RxStatusWriteLatched_syncb ) {
2023-06-29 18:29:54 +08:00
RxStatusWriteLatched : = false . B
} . elsewhen ( RxStatusWrite ) {
RxStatusWriteLatched : = true . B
}
// Tx Done Interrupt
when ( TxStatusWrite & TxIRQEn ) {
TxB_IRQ : = ~ TxError
} . otherwise {
TxB_IRQ : = false . B
}
// Tx Error Interrupt
when ( TxStatusWrite & TxIRQEn ) {
TxE_IRQ : = TxError
} . otherwise {
TxE_IRQ : = false . B
}
// Rx Done Interrupt
2023-07-20 10:35:56 +08:00
when ( RxStatusWrite & RxIRQEn & io . ReceivedPacketGood & ( ~ io . ReceivedPauseFrm | io . ReceivedPauseFrm & io . r_PassAll & ( ~ io . r_RxFlow ) ) ) {
2023-06-29 18:29:54 +08:00
RxB_IRQ : = ( ~ RxError )
} . otherwise {
RxB_IRQ : = false . B
}
// Rx Error Interrupt
2023-07-20 10:35:56 +08:00
when ( RxStatusWrite & RxIRQEn & ( ~ io . ReceivedPauseFrm | io . ReceivedPauseFrm & io . r_PassAll & ( ~ io . r_RxFlow ) ) ) {
2023-06-29 18:29:54 +08:00
RxE_IRQ : = RxError
} . otherwise {
RxE_IRQ : = false . B
}
2023-10-08 15:13:35 +08:00
io . Busy_IRQ : = io . Busy_IRQ_sync & ~ RegNext ( io . Busy_IRQ_sync )
2023-06-29 18:29:54 +08:00
2023-06-30 20:21:03 +08:00
2023-07-03 16:25:41 +08:00
2023-07-20 14:58:59 +08:00
2023-10-08 10:12:49 +08:00
BDCs : = Fill ( 4 , io . tlSlv . A . valid & io . tlSlv . A . bits . mask . orR & io . tlSlv . A . bits . address ( 10 ) ) & io . tlSlv . A . bits . mask // 0x400 - 0x7FF
2023-07-03 16:25:41 +08:00
2023-07-11 17:38:18 +08:00
val slvAInfo = RegEnable ( io . tlSlv . A . bits , io . tlSlv . A . fire )
val slvDValid = RegInit ( false . B ) ; io . tlSlv . D . valid : = slvDValid
2023-07-04 15:40:51 +08:00
val slvDDat = Reg ( UInt ( 32. W ) )
2023-07-04 17:37:41 +08:00
2023-07-11 17:38:18 +08:00
when ( io . tlSlv . D . fire ) {
2023-07-04 15:40:51 +08:00
slvDValid : = false . B
2023-07-11 17:38:18 +08:00
} . elsewhen ( io . tlSlv . A . fire ) {
2023-07-04 15:40:51 +08:00
slvDValid : = true . B
2023-07-20 14:58:59 +08:00
slvDDat : = BD_WB_DAT_O
2023-07-04 15:40:51 +08:00
}
2023-06-30 20:21:03 +08:00
2023-07-04 15:40:51 +08:00
when ( slvAInfo . opcode === 4. U ) {
2023-07-11 17:38:18 +08:00
io . tlSlv . D . bits : = edgeIn . AccessAck ( slvAInfo , slvDDat )
2023-07-04 15:40:51 +08:00
} . otherwise {
2023-07-11 17:38:18 +08:00
io . tlSlv . D . bits : = edgeIn . AccessAck ( slvAInfo )
2023-07-04 15:40:51 +08:00
}
2023-06-29 18:29:54 +08:00
2023-07-20 14:58:59 +08:00
io . tlSlv . A . ready : = BDAck
2023-07-11 17:38:18 +08:00
assert ( ~ ( io . tlSlv . A . ready & ~ io . tlSlv . A . valid ) )
2023-07-04 17:37:41 +08:00
2023-07-21 16:38:02 +08:00
// when( io.tlSlv.A.fire & (~(io.tlSlv.A.bits.mask.orR) | CsMiss) ){
// assert( false.B, "Assert Failed, tileLink access an undefine region!" )
// }
2023-07-20 10:35:56 +08:00
2023-07-07 21:43:06 +08:00
val mstAValid = RegInit ( false . B )
val mstABits = Reg ( new TLBundleA ( edgeOut . bundle ) )
// val tlMstStateDnxt = WireDefault()
// val tlMstState = RegNext( )
2023-07-11 17:38:18 +08:00
when ( io . tlMst . A . fire ) {
2023-07-07 21:43:06 +08:00
mstAValid : = false . B
}
. elsewhen ( MasterWbRX & ~ isTlMstBusy ) {
mstAValid : = true . B
mstABits : =
edgeOut . Put (
fromSource = 0. U ,
2023-07-11 00:00:26 +08:00
toAddress = RxPointerMSB << 2 ,
2023-07-07 21:43:06 +08:00
lgSize = log2Ceil ( 32 / 8 ) . U ,
data = rx_fifo . io . data_out ,
2023-09-27 16:31:56 +08:00
mask = "b1111" . U ,
2023-07-07 21:43:06 +08:00
) . _2
}
. elsewhen ( MasterWbTX & ~ isTlMstBusy ) {
mstAValid : = true . B
mstABits : =
edgeOut . Get (
fromSource = 0. U ,
2023-07-11 00:00:26 +08:00
toAddress = TxPointerMSB << 2 ,
2023-07-07 21:43:06 +08:00
lgSize = log2Ceil ( 32 / 8 ) . U ,
) . _2
}
2023-07-11 17:38:18 +08:00
when ( io . tlMst . A . fire ) {
2023-07-07 21:43:06 +08:00
isTlMstBusy : = true . B
2023-07-11 17:38:18 +08:00
} . elsewhen ( io . tlMst . D . fire ) {
2023-07-07 21:43:06 +08:00
isTlMstBusy : = false . B
}
when ( ~ MasterWbTX & ~ MasterWbRX ) {
when ( WriteRxDataToMemory ) {
MasterWbRX : = true . B
} . elsewhen ( ReadTxDataFromMemory_2 ) {
MasterWbTX : = true . B
}
} . elsewhen ( ~ MasterWbTX & MasterWbRX ) { //1.4A + 1D fifo to memory
2023-07-11 17:38:18 +08:00
when ( io . tlMst . D . fire & isLastD & ~ WriteRxDataToMemory ) {
2023-07-07 21:43:06 +08:00
MasterWbRX : = false . B
}
} . elsewhen ( MasterWbTX & ~ MasterWbRX ) { //1 A + 1.4D memory to fifo
2023-07-11 17:38:18 +08:00
when ( io . tlMst . D . fire & isLastD & ~ ReadTxDataFromMemory_2 ) {
2023-07-07 21:43:06 +08:00
MasterWbTX : = false . B
}
}
2023-07-11 17:38:18 +08:00
when ( io . tlMst . D . fire & io . tlMst . D . bits . opcode === 1. U ) { assert ( MasterWbTX ) }
when ( io . tlMst . D . fire & io . tlMst . D . bits . opcode === 0. U ) { assert ( MasterWbRX ) }
2023-07-07 21:43:06 +08:00
2023-07-11 00:00:26 +08:00
val tlMstAValid_dbg = RegInit ( true . B )
2023-07-11 17:38:18 +08:00
io . tlMst . A . valid : = mstAValid & tlMstAValid_dbg
io . tlMst . A . bits : = mstABits
2023-07-07 21:43:06 +08:00
2023-07-11 00:00:26 +08:00
val tlMstDReady = RegInit ( true . B )
dontTouch ( tlMstDReady )
dontTouch ( tlMstAValid_dbg )
2023-07-11 17:38:18 +08:00
io . tlMst . D . ready : = tlMstDReady
2023-07-07 21:43:06 +08:00
2023-07-03 16:25:41 +08:00
}
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
trait MacTileLinkTXClk { this : MacTileLinkBase =>
2023-10-08 11:34:36 +08:00
// val macTileLinkTX = withClockAndReset( io.MTxClk.asClock, io.asyncReset ) (Module(new MacTileLinkTX))
2023-10-07 16:44:13 +08:00
2023-10-08 11:34:36 +08:00
// withClockAndReset( io.MTxClk.asClock, io.asyncReset ){
// macTileLinkTX.io.BlockingTxStatusWrite_sync := ShiftRegister(BlockingTxStatusWrite, 2, false.B, true.B)
// macTileLinkTX.io.TxStartFrm_sync := ShiftRegister( TxStartFrm_wb, 2, false.B, true.B ) // Synchronizing TxStartFrm_wb to MTxClk
// macTileLinkTX.io.ReadTxDataFromFifo_syncb := ShiftRegister(ReadTxDataFromFifo_sync(1), 2, false.B, true.B)
// }
2023-10-07 16:44:13 +08:00
2023-10-08 11:34:36 +08:00
// TxStartFrm_syncb := ShiftRegister( macTileLinkTX.io.TxStartFrm_sync, 2, false.B, true.B )
2023-10-07 16:44:13 +08:00
2023-10-08 11:34:36 +08:00
// io.RstDeferLatched := macTileLinkTX.io.RstDeferLatched
// io.TxStartFrm := macTileLinkTX.io.TxStartFrm
// io.TxEndFrm := macTileLinkTX.io.TxEndFrm
// io.TxData := macTileLinkTX.io.TxData
// io.TxUnderRun := macTileLinkTX.io.TxUnderRun
2023-10-07 16:44:13 +08:00
2023-10-08 11:34:36 +08:00
// macTileLinkTX.io.TxUnderRun_wb := TxUnderRun_wb
// macTileLinkTX.io.TxData_wb := TxData_wb
// macTileLinkTX.io.TxValidBytesLatched := TxValidBytesLatched
// macTileLinkTX.io.TxEndFrm_wb := TxEndFrm_wb
2023-10-07 16:44:13 +08:00
2023-10-08 11:34:36 +08:00
// ReadTxDataFromFifo_tck_txclk := macTileLinkTX.io.ReadTxDataFromFifo_tck
2023-10-07 16:44:13 +08:00
2023-10-08 11:34:36 +08:00
// macTileLinkTX.io.TxUsedData := io.TxUsedData
// macTileLinkTX.io.TxRetry := io.TxRetry
// macTileLinkTX.io.TxAbort := io.TxAbort
// macTileLinkTX.io.TxDone := io.TxDone
2023-10-07 16:44:13 +08:00
}
trait MacTileLinkRXClk { this : MacTileLinkBase =>
2023-10-08 15:13:35 +08:00
// val macTileLinkRX = withClockAndReset( io.MRxClk.asClock, io.asyncReset ) ( Module(new MacTileLinkRX) )
// RxDataLatched2_rxclk := macTileLinkRX.io.RxDataLatched2
// WriteRxDataToFifo_rxclk := macTileLinkRX.io.WriteRxDataToFifo
// RxAbortLatched_rxclk := macTileLinkRX.io.RxAbortLatched
// LatchedRxLength_rxclk := macTileLinkRX.io.LatchedRxLength
// RxStatusInLatched_rxclk := macTileLinkRX.io.RxStatusInLatched
// ShiftEnded_rck_rxclk := macTileLinkRX.io.ShiftEnded_rck
// LatchedRxStartFrm_rxclk := macTileLinkRX.io.LatchedRxStartFrm
2023-10-07 16:44:13 +08:00
2023-10-08 10:12:49 +08:00
2023-10-08 15:13:35 +08:00
// // Busy Interrupt
// val Busy_IRQ_sync = ShiftRegisters(macTileLinkRX.io.Busy_IRQ_rck, 3)
// io.Busy_IRQ := Busy_IRQ_sync(1) & ~Busy_IRQ_sync(2)
// withClockAndReset( io.MRxClk.asClock, io.asyncReset ) {
// macTileLinkRX.io.ShiftEndedSync := ShiftRegisters(ShiftEndedSync(1), 2, false.B, true.B)
// macTileLinkRX.io.RxAbortSyncb := ShiftRegister( RxAbortSync(1), 2, false.B, true.B )
// io.RxStatusWriteLatched_sync2 := ShiftRegister(RxStatusWriteLatched, 2, false.B, true.B)
// macTileLinkRX.io.Busy_IRQ_syncb := ShiftRegister( Busy_IRQ_sync(1), 2, false.B, true.B )
// macTileLinkRX.io.WriteRxDataToFifoSyncb := ShiftRegister( WriteRxDataToFifoSync(1), 2, false.B, true.B )
// macTileLinkRX.io.SyncRxStartFrmSyncb := ShiftRegister( SyncRxStartFrmSync(1), 2, false.B, true.B )
// macTileLinkRX.io.RxReady := ShiftRegister( RxReady, 2, false.B, true.B )
// }
2023-10-07 16:44:13 +08:00
2023-10-08 15:13:35 +08:00
// macTileLinkRX.io.RxData := io.RxData
// macTileLinkRX.io.RxAbort := io.RxAbort
// macTileLinkRX.io.RxValid := io.RxValid
2023-10-07 16:44:13 +08:00
2023-10-08 15:13:35 +08:00
// macTileLinkRX.io.RxStartFrm := io.RxStartFrm
// macTileLinkRX.io.RxEndFrm := io.RxEndFrm
2023-10-07 16:44:13 +08:00
2023-10-08 15:13:35 +08:00
// macTileLinkRX.io.RxLength := io.RxLength
// macTileLinkRX.io.LoadRxStatus := io.LoadRxStatus
// macTileLinkRX.io.RxStatusIn := RxStatusIn
2023-10-07 16:44:13 +08:00
}
class MacTileLink ( edgeIn : TLEdgeIn , edgeOut : TLEdgeOut ) extends MacTileLinkBase ( edgeIn , edgeOut ) with MacTileLinkTXClk with MacTileLinkRXClk
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
class MacTileLinkTXIO extends Bundle {
2023-10-07 16:44:13 +08:00
val RstDeferLatched = Output ( Bool ( ) )
2023-09-28 18:45:14 +08:00
val BlockingTxStatusWrite_sync = Input ( Bool ( ) )
val TxStartFrm_sync = Input ( Bool ( ) )
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
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 TxUnderRun = Output ( Bool ( ) ) // Transmit packet under-run
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
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
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
val ReadTxDataFromFifo_tck = Output ( Bool ( ) )
2023-10-07 16:44:13 +08:00
val ReadTxDataFromFifo_syncb = Input ( Bool ( ) )
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
val TxEndFrm_wb = Input ( Bool ( ) )
2023-10-07 16:44:13 +08:00
val TxValidBytesLatched = Input ( UInt ( 2. W ) )
2023-09-28 18:45:14 +08:00
val TxData_wb = Input ( UInt ( 32. W ) )
val TxUnderRun_wb = Input ( Bool ( ) )
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
class MacTileLinkTX extends Module with RequireAsyncReset {
val io = IO ( new MacTileLinkTXIO )
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
io . RstDeferLatched : = io . BlockingTxStatusWrite_sync & ~ RegNext ( io . BlockingTxStatusWrite_sync , false . B )
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
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 TxUnderRun = RegInit ( false . B ) ; io . TxUnderRun : = TxUnderRun
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
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// 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 )
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// 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 ) ,
) )
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// 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 ) ,
) )
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
val TxUnderRun_sync1 = RegInit ( false . B )
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// Tx under run
when ( io . TxUnderRun_wb ) {
TxUnderRun_sync1 : = true . B
} . elsewhen ( io . BlockingTxStatusWrite_sync ) {
TxUnderRun_sync1 : = false . B
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// Tx under run
when ( io . BlockingTxStatusWrite_sync ) {
TxUnderRun : = false . B
} . elsewhen ( TxUnderRun_sync1 ) {
TxUnderRun : = true . B
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
when ( io . TxStartFrm_sync & ~ TxStartFrm | io . TxUsedData & Flop & TxByteCnt === 3. U &
~ LastWord | TxStartFrm & io . TxUsedData & Flop & TxByteCnt === 0. U ) {
ReadTxDataFromFifo_tck : = true . B
2023-10-07 16:44:13 +08:00
} . elsewhen ( io . ReadTxDataFromFifo_syncb & ~ RegNext ( io . ReadTxDataFromFifo_syncb , false . B ) ) {
2023-09-28 18:45:14 +08:00
ReadTxDataFromFifo_tck : = false . B
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
}
2023-06-29 18:29:54 +08:00
2023-09-28 18:45:14 +08:00
// trait MacTileLinkTXClk{ this: MacTileLinkBase =>
// withClockAndReset( io.MTxClk.asClock, io.asyncReset ) {
// val Flop = RegInit(false.B)
// val BlockingTxStatusWrite_sync = ShiftRegisters(BlockingTxStatusWrite, 3, false.B, true.B) // Synchronizing BlockingTxStatusWrite to MTxClk
// io.RstDeferLatched := BlockingTxStatusWrite_sync(1) & ~BlockingTxStatusWrite_sync(2)
// val TxStartFrm_sync = ShiftRegister( TxStartFrm_wb, 2, false.B, true.B ); TxStartFrm_sync_txclk := TxStartFrm_sync// Synchronizing TxStartFrm_wb to MTxClk
// 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 TxUnderRun = RegInit(false.B); io.TxUnderRun := TxUnderRun
// 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); ReadTxDataFromFifo_tck_txclk := 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)
// val ReadTxDataFromFifo_syncb = ShiftRegisters(ReadTxDataFromFifo_sync(1), 3, false.B, true.B)
// // Changes for tx occur every second clock. Flop is used for this manner.
// when( io.TxDone | io.TxAbort | TxRetry_q){
// Flop := false.B
// } .elsewhen ( io.TxUsedData ){
// Flop := ~Flop
// }
// when(TxStartFrm_sync){
// TxStartFrm := true.B
// } .elsewhen(TxUsedData_q | ~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 := TxEndFrm_wb
// }
// // Tx end frame generation
// when(Flop & TxEndFrm | io.TxAbort | TxRetry_q){
// TxEndFrm := false.B
// } .elsewhen(Flop & LastWord){
// TxEndFrm :=
// Mux1H(Seq(
// (TxValidBytesLatched === 1.U) -> (TxByteCnt === 0.U),
// (TxValidBytesLatched === 2.U) -> (TxByteCnt === 1.U),
// (TxValidBytesLatched === 3.U) -> (TxByteCnt === 2.U),
// (TxValidBytesLatched === 0.U) -> (TxByteCnt === 3.U),
// ))
// }
// // Tx data selection (latching)
// when( TxStartFrm_sync & ~TxStartFrm ){
// TxData := 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(
// TxStartFrm_sync & ~TxStartFrm |
// io.TxUsedData & Flop & TxByteCnt === 3.U |
// TxStartFrm & io.TxUsedData & Flop & TxByteCnt === 0.U){
// TxDataLatched := TxData_wb
// }
// val TxUnderRun_sync1 = RegInit(false.B)
// // Tx under run
// when(TxUnderRun_wb){
// TxUnderRun_sync1 := true.B
// } .elsewhen(BlockingTxStatusWrite_sync(1)){
// TxUnderRun_sync1 := false.B
// }
// // Tx under run
// when(BlockingTxStatusWrite_sync(1)){
// TxUnderRun := false.B
// } .elsewhen(TxUnderRun_sync1){
// TxUnderRun := true.B
// }
// // 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(TxStartFrm_sync & ~TxStartFrm | io.TxUsedData & Flop & TxByteCnt === 3.U &
// ~LastWord | TxStartFrm & io.TxUsedData & Flop & TxByteCnt === 0.U ){
// ReadTxDataFromFifo_tck := true.B
// } .elsewhen(ReadTxDataFromFifo_syncb(1) & ~ReadTxDataFromFifo_syncb(2)){
// ReadTxDataFromFifo_tck := false.B
// }
// }
// }
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
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 LatchedRxStartFrm = Output ( Bool ( ) )
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
val RxLength = Input ( UInt ( 16. W ) )
val LoadRxStatus = Input ( Bool ( ) )
2023-10-08 10:12:49 +08:00
val RxStatusIn = Input ( UInt ( 9. W ) )
2023-10-08 15:13:35 +08:00
val ShiftEndedSyncb = Input ( Bool ( ) )
2023-10-07 16:44:13 +08:00
val RxAbortSyncb = Input ( Bool ( ) )
2023-10-08 10:12:49 +08:00
val WriteRxDataToFifoSyncb = Input ( Bool ( ) )
val SyncRxStartFrmSyncb = Input ( Bool ( ) )
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
val Busy_IRQ_rck = Output ( Bool ( ) )
val Busy_IRQ_syncb = Input ( Bool ( ) )
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
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 ( ) )
}
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
class MacTileLinkRX extends Module with RequireAsyncReset {
val io = IO ( new MacTileLinkRXIO )
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
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
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
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
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
val ShiftEnded_rck = RegInit ( false . B ) ; io . ShiftEnded_rck : = ShiftEnded_rck
val RxEnableWindow = RegInit ( false . B )
val LatchedRxStartFrm = RegInit ( false . B ) ; io . LatchedRxStartFrm : = LatchedRxStartFrm
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
val Busy_IRQ_rck = RegInit ( false . B ) ; io . Busy_IRQ_rck : = Busy_IRQ_rck
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
// 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
}
2023-06-29 18:29:54 +08:00
2023-10-07 16:44:13 +08:00
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 ,
2023-06-28 23:43:03 +08:00
) )
}
2023-10-07 16:44:13 +08:00
}
// 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 ) ,
) )
}
2023-06-28 23:43:03 +08:00
2023-06-29 21:14:51 +08:00
when ( SetWriteRxDataToFifo & ~ io . RxAbort ) {
2023-06-28 23:43:03 +08:00
WriteRxDataToFifo : = true . B
2023-10-08 10:12:49 +08:00
} . elsewhen ( io . WriteRxDataToFifoSyncb | io . RxAbort ) {
2023-06-28 23:43:03 +08:00
WriteRxDataToFifo : = false . B
}
2023-10-08 10:12:49 +08:00
when ( io . RxStartFrm & ~ io . SyncRxStartFrmSyncb ) {
2023-06-28 23:43:03 +08:00
LatchedRxStartFrm : = true . B
2023-10-08 10:12:49 +08:00
} . elsewhen ( io . SyncRxStartFrmSyncb ) {
2023-06-28 23:43:03 +08:00
LatchedRxStartFrm : = false . B
}
// Generation of the end-of-frame signal
2023-06-29 21:14:51 +08:00
when ( ~ io . RxAbort & SetWriteRxDataToFifo & StartShiftWillEnd ) {
2023-06-28 23:43:03 +08:00
ShiftEnded_rck : = true . B
2023-10-08 15:13:35 +08:00
} . elsewhen ( io . RxAbort | io . ShiftEndedSyncb & RegNext ( io . ShiftEndedSyncb , false . B ) ) {
2023-06-28 23:43:03 +08:00
ShiftEnded_rck : = false . B
}
2023-06-30 16:14:58 +08:00
// Generation of the end-of-frame signal
2023-06-29 21:14:51 +08:00
when ( io . RxStartFrm ) {
2023-06-28 23:43:03 +08:00
RxEnableWindow : = true . B
2023-06-29 18:29:54 +08:00
} . elsewhen ( io . RxEndFrm | io . RxAbort ) {
2023-06-28 23:43:03 +08:00
RxEnableWindow : = false . B
}
2023-10-07 16:44:13 +08:00
when ( io . RxAbortSyncb ) {
2023-06-28 23:43:03 +08:00
RxAbortLatched : = false . B
2023-06-29 18:29:54 +08:00
} . elsewhen ( io . RxAbort ) {
2023-06-28 23:43:03 +08:00
RxAbortLatched : = true . B
}
2023-10-07 16:44:13 +08:00
when ( io . RxValid & io . RxStartFrm & ~ io . RxReady ) {
Busy_IRQ_rck : = true . B
} . elsewhen ( io . Busy_IRQ_syncb ) {
Busy_IRQ_rck : = false . B
}
2023-06-28 23:43:03 +08:00
2023-10-07 16:44:13 +08:00
}
2023-06-30 16:14:58 +08:00
2023-06-28 23:43:03 +08:00
2023-06-30 16:14:58 +08:00
2023-06-28 23:43:03 +08:00
2023-10-07 16:44:13 +08:00
// trait MacTileLinkRXClk{ this: MacTileLinkBase =>
// withClockAndReset( io.MRxClk.asClock, io.asyncReset ){
// val RxDataLatched2 = RegInit(0.U(32.W)); RxDataLatched2_rxclk := 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)); RxByteCnt_rxclk := RxByteCnt
// val LastByteIn = RegInit(false.B); LastByteIn_rxclk := LastByteIn
// val ShiftWillEnd = RegInit(false.B); ShiftWillEnd_rxclk := ShiftWillEnd
// val WriteRxDataToFifo = RegInit(false.B); WriteRxDataToFifo_rxclk := WriteRxDataToFifo
// val RxAbortLatched = RegInit(false.B); RxAbortLatched_rxclk := RxAbortLatched
// val LatchedRxLength = RegEnable(io.RxLength, 0.U(16.W), io.LoadRxStatus); LatchedRxLength_rxclk := LatchedRxLength
// val RxStatusInLatched = RegEnable(RxStatusIn, 0.U(9.W), io.LoadRxStatus); RxStatusInLatched_rxclk := RxStatusInLatched
// val ShiftEnded_rck = RegInit(false.B); ShiftEnded_rck_txclk := ShiftEnded_rck
2023-10-08 15:13:35 +08:00
// val ShiftEndedSyncb = ShiftRegisters(ShiftEndedSync2, 2, false.B, true.B)
2023-10-07 16:44:13 +08:00
// val RxAbortSyncb = ShiftRegister( RxAbortSync(1), 2, false.B, true.B )
// val RxEnableWindow = RegInit(false.B); RxEnableWindow_rxclk := RxEnableWindow
// val LatchedRxStartFrm = RegInit(false.B); LatchedRxStartFrm_rxclk := LatchedRxStartFrm
// val RxStatusWriteLatched_sync = ShiftRegister(RxStatusWriteLatched, 2, false.B, true.B); io.RxStatusWriteLatched_sync2 := RxStatusWriteLatched_sync
// // Indicating that last byte is being reveived
// when(ShiftWillEnd & RxByteCnt.andR | io.RxAbort){
// LastByteIn := false.B
// } .elsewhen(io.RxValid & RxReady & io.RxEndFrm & ~(RxByteCnt.andR) & RxEnableWindow){
// LastByteIn := true.B
// }
// // Indicating that data reception will end
// 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 & RxReady){
// RxByteCnt := 1.U
// } .elsewhen(io.RxValid & RxEnableWindow & 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 & 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,
// ))
// }
// }
// // 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(WriteRxDataToFifoSync(1) | io.RxAbort){
// WriteRxDataToFifo := false.B
// }
// when(io.RxStartFrm & ~SyncRxStartFrm(1)){
// LatchedRxStartFrm := true.B
// } .elsewhen(SyncRxStartFrm(1)){
// LatchedRxStartFrm := false.B
// }
// // Generation of the end-of-frame signal
// when(~io.RxAbort & SetWriteRxDataToFifo & StartShiftWillEnd){
// ShiftEnded_rck := true.B
2023-10-08 15:13:35 +08:00
// } .elsewhen(io.RxAbort | ShiftEndedSyncb(0) & ShiftEndedSyncb(1)){
2023-10-07 16:44:13 +08:00
// 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(RxAbortSyncb){
// RxAbortLatched := false.B
// } .elsewhen(io.RxAbort){
// RxAbortLatched := true.B
// }
// val Busy_IRQ_rck = RegInit(false.B); Busy_IRQ_rck_rxclk := Busy_IRQ_rck
// val Busy_IRQ_syncb = ShiftRegister( Busy_IRQ_sync(1), 2, false.B, true.B )
// when(io.RxValid & io.RxStartFrm & ~RxReady){
// Busy_IRQ_rck := true.B
// } .elsewhen(Busy_IRQ_syncb){
// Busy_IRQ_rck := false.B
// }
// }
// }
2023-06-28 23:43:03 +08:00