2023-06-28 23:43:03 +08:00
package MAC
import chisel3._
import chisel3.util._
2023-06-29 23:28:05 +08:00
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
}
2023-06-28 23:43:03 +08:00
class MacTileLinkIO extends Bundle {
2023-06-29 18:29:54 +08:00
// WISHBONE common
val WB_DAT_I = Input ( UInt ( 32. W ) ) // WISHBONE data input
val WB_DAT_O = Output ( UInt ( 32. W ) ) // WISHBONE data output
// WISHBONE slave
val WB_ADR_I = Input ( UInt ( 8. W ) ) // WISHBONE address input
val WB_WE_I = Input ( Bool ( ) ) // WISHBONE write enable input
val BDCs = Input ( UInt ( 4. W ) ) // Buffer descriptors are selected
val WB_ACK_O = Output ( Bool ( ) ) // WISHBONE acknowledge output
// WISHBONE master
val m_wb_adr_o = Output ( UInt ( 30. W ) )
val m_wb_sel_o = Output ( UInt ( 4. W ) )
val m_wb_we_o = Output ( Bool ( ) )
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_dat_i = Input ( UInt ( 32. W ) )
val m_wb_ack_i = Input ( Bool ( ) )
val m_wb_err_i = Input ( Bool ( ) )
val m_wb_cti_o = Output ( UInt ( 3. W ) ) // Cycle Type Identifier
val m_wb_bte_o = Output ( UInt ( 2. W ) ) // Burst Type Extension
// 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 RxLength = Input ( UInt ( 16. W ) ) // Length of the incoming frame
val LoadRxStatus = Input ( Bool ( ) ) // Rx status was loaded
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
val r_RxFlow = Input ( Bool ( ) )
val r_PassAll = Input ( Bool ( ) )
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 RstDeferLatched = Output ( Bool ( ) )
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
val TxRetry = Input ( Bool ( ) ) // Transmit packet retry
val TxAbort = Input ( Bool ( ) ) // Transmit packet abort
val TxDone = Input ( Bool ( ) ) // Transmission ended
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
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 RxData = Input ( UInt ( 8. W ) ) // Received data byte (from PHY)
val RxValid = Input ( Bool ( ) )
val RxStartFrm = Input ( Bool ( ) )
val RxEndFrm = Input ( Bool ( ) )
val RxAbort = Input ( Bool ( ) ) // This signal is set when address doesn't match.
val RxStatusWriteLatched_sync2 = Output ( Bool ( ) )
//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
2023-06-28 23:43:03 +08:00
// 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-06-29 18:29:54 +08:00
abstract class MacTileLinkBase extends Module {
val io : MacTileLinkIO = IO ( new MacTileLinkIO )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +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
val TxUnderRun_wb = RegInit ( false . B )
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-29 23:28:05 +08:00
// Synchronizing TxRetry TxDone_wb TxAbort signal (synchronized to WISHBONE clock)
2023-06-30 16:00:02 +08:00
2023-06-28 23:43:03 +08:00
val TxStartFrm_wb = RegInit ( false . B )
// Generating delayed signals
2023-06-30 16:00:02 +08:00
val TxRetry_wb = ShiftRegisters ( io . TxRetry , 3 , false . B , true . B )
val TxAbort_wb = ShiftRegisters ( io . TxAbort , 3 , false . B , true . B )
val TxDone_wb = ShiftRegisters ( io . TxDone , 3 , false . B , true . B )
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 )
val RxReady = RegInit ( false . B )
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
val BlockingTxStatusWrite = RegInit ( false . B )
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
val TxEndFrm_wb = RegInit ( false . B )
val TxRetryPulse = Wire ( Bool ( ) )
val TxDonePulse = Wire ( Bool ( ) )
val TxAbortPulse = Wire ( Bool ( ) )
2023-06-29 18:29:54 +08:00
val StartRxBDRead = Wire ( Bool ( ) )
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-29 18:29:54 +08:00
val WB_ACK_O = Reg ( Bool ( ) ) ; io . WB_ACK_O : = WB_ACK_O
val RxStatusIn = Wire ( UInt ( 9. W ) )
2023-06-28 23:43:03 +08:00
// Delayed stage signals
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 )
val r_TxEn_q = RegNext ( io . r_TxEn , false . B )
val r_RxEn_q = RegNext ( io . r_RxEn , false . B )
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 StartRxPointerRead = Wire ( Bool ( ) )
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 ShiftEnded_rck_txclk = Wire ( Bool ( ) )
val ShiftEndedSync1 = RegNext ( ShiftEnded_rck_txclk , false . B )
val ShiftEndedSync2 = RegNext ( ShiftEndedSync1 , false . B )
val ShiftEndedSync3 = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val StartShiftWillEnd = Wire ( Bool ( ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val StartOccured = RegInit ( false . B )
2023-06-30 16:00:02 +08:00
val TxStartFrm_sync2_txclk = Wire ( Bool ( ) )
val TxStartFrm_syncb1 = RegNext ( TxStartFrm_sync2_txclk , false . B )
val TxStartFrm_syncb2 = RegNext ( TxStartFrm_syncb1 , false . B )
2023-06-28 23:43:03 +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 tx_burst_en = RegInit ( true . B )
val rx_burst_en = RegInit ( false . B )
val tx_burst_cnt = RegInit ( 0. U ( 3. W ) )
2023-06-28 23:43:03 +08:00
2023-06-30 16:00:02 +08:00
// val tx_burst = Wire(Bool())
2023-06-29 18:29:54 +08:00
val m_wb_cti_o = RegInit ( 0. U ( 3. W ) ) ; io . m_wb_cti_o : = m_wb_cti_o // Cycle Type Identifier
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val TxData_wb = Wire ( UInt ( 32. W ) )
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 rx_burst_cnt = RegInit ( 0. U ( 3. W ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val rx_burst = Wire ( Bool ( ) )
val enough_data_in_rxfifo_for_burst = Wire ( Bool ( ) )
val enough_data_in_rxfifo_for_burst_plus1 = Wire ( Bool ( ) )
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 m_wb_adr_o = RegInit ( 0. U ( 30. W ) ) ; io . m_wb_adr_o : = m_wb_adr_o
val m_wb_cyc_o = RegInit ( false . B ) ; io . m_wb_cyc_o : = m_wb_cyc_o
val m_wb_sel_o = RegInit ( 0. U ( 4. W ) ) ; io . m_wb_sel_o : = m_wb_sel_o
val m_wb_we_o = RegInit ( false . B ) ; io . m_wb_we_o : = m_wb_we_o
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val BlockingIncrementTxPointer = RegInit ( false . B )
val TxPointerMSB = RegInit ( 0. U ( 30. W ) ) //[31:2]
val TxPointerLSB = RegInit ( 0. U ( 2. W ) )
val TxPointerLSB_rst = RegInit ( 0. U ( 2. W ) )
val RxPointerMSB = RegInit ( 0. U ( 30. W ) ) //[31:2]
val RxPointerLSB_rst = RegInit ( 0. U ( 2. W ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val cyc_cleared = RegInit ( false . B )
val IncrTxPointer = RegInit ( false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val RxByteSel = Wire ( UInt ( 4. W ) )
val MasterAccessFinished = Wire ( Bool ( ) )
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-06-29 18:29:54 +08:00
// Start: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I
val ReadTxDataFromFifo_tck_txclk = Wire ( Bool ( ) )
val ReadTxDataFromFifo_sync1 = RegNext ( ReadTxDataFromFifo_tck_txclk , false . B )
val ReadTxDataFromFifo_sync2 = RegNext ( ReadTxDataFromFifo_sync1 , false . B )
val ReadTxDataFromFifo_sync3 = RegNext ( ReadTxDataFromFifo_sync2 , false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val RxAbortLatched_rxclk = Wire ( Bool ( ) )
val RxAbortSync1 = RegNext ( RxAbortLatched_rxclk , false . B )
val RxAbortSync2 = RegNext ( RxAbortSync1 , false . B )
val RxAbortSync3 = RegNext ( RxAbortSync2 , false . B )
val RxAbortSync4 = RegNext ( RxAbortSync3 , false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val SetWriteRxDataToFifo = Wire ( Bool ( ) )
val WriteRxDataToFifo_rxclk = Wire ( Bool ( ) )
val WriteRxDataToFifoSync1 = RegNext ( WriteRxDataToFifo_rxclk , false . B )
val WriteRxDataToFifoSync2 = RegNext ( WriteRxDataToFifoSync1 , false . B )
val WriteRxDataToFifoSync3 = RegNext ( WriteRxDataToFifoSync2 , false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val WriteRxDataToFifo_wb = Wire ( Bool ( ) )
val LatchedRxStartFrm_rxclk = Wire ( Bool ( ) )
val SyncRxStartFrm = RegNext ( LatchedRxStartFrm_rxclk , false . B )
val SyncRxStartFrm_q = RegNext ( SyncRxStartFrm , false . B )
val SyncRxStartFrm_q2 = RegNext ( SyncRxStartFrm_q , false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val RxFifoReset = Wire ( Bool ( ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val TxError = Wire ( Bool ( ) )
val RxError = Wire ( Bool ( ) )
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-29 18:29:54 +08:00
val RxStatusWriteLatched_syncb1 = RegNext ( io . RxStatusWriteLatched_sync2 , false . B )
val RxStatusWriteLatched_syncb2 = RegNext ( RxStatusWriteLatched_syncb1 , false . B )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
io . m_wb_bte_o : = "b00" . U // Linear burst
io . m_wb_stb_o : = m_wb_cyc_o
when ( true . B ) {
WB_ACK_O : = ( BDWrite . orR & WbEn & WbEn_q ) | ( BDRead & WbEn & ~ WbEn_q )
}
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-29 18:29:54 +08:00
io . 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 : =
( BDWrite & Fill ( 4 , ( WbEn & WbEn_q ) ) ) |
Fill ( 4 , ( TxStatusWrite | RxStatusWrite ) )
ram_oe : =
( BDRead & WbEn & WbEn_q ) |
( TxEn & TxEn_q & ( TxBDRead | TxPointerRead ) ) |
( RxEn & RxEn_q & ( RxBDRead | RxPointerRead ) )
when ( ~ TxBDReady & io . r_TxEn & WbEn & ~ WbEn_q ) {
TxEn_needed : = true . B
} . elsewhen ( TxPointerRead & TxEn & TxEn_q ) {
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.
val RAMAccessEnable =
Cat ( WbEn_q , RxEn_q , TxEn_q , RxEn_needed , TxEn_needed )
2023-06-29 18:29:54 +08:00
// Switching between three stages depends on enable signals
2023-06-30 14:46:23 +08:00
when ( RAMAccessEnable === BitPat ( "b1001?" ) ) { // synopsys parallel_case
2023-06-29 18:29:54 +08:00
WbEn : = false . B
RxEn : = true . B // wb access stage and r_RxEn is enabled
TxEn : = false . B
ram_addr : = Cat ( RxBDAddress , RxPointerRead )
ram_di : = RxBDDataIn
2023-06-30 14:46:23 +08:00
} . elsewhen ( RAMAccessEnable === BitPat ( "b10001" ) ) {
2023-06-29 18:29:54 +08:00
WbEn : = false . B
RxEn : = false . B
TxEn : = true . B // wb access stage, r_RxEn is disabled but r_TxEn is enabled
2023-06-30 14:46:23 +08:00
ram_addr : = Cat ( TxBDAddress , TxPointerRead ) //[7,1] + [0]
ram_di : = TxBDDataIn
} . elsewhen ( RAMAccessEnable === BitPat ( "b010?0" ) ) {
2023-06-29 18:29:54 +08:00
WbEn : = true . B // RxEn access stage and r_TxEn is disabled
RxEn : = false . B
TxEn : = false . B
2023-06-30 14:46:23 +08:00
ram_addr : = io . WB_ADR_I // [9:2];
ram_di : = io . WB_DAT_I ;
BDWrite : = io . BDCs & Fill ( 4 , io . WB_WE_I )
BDRead : = io . BDCs . orR & ~ io . WB_WE_I
} . elsewhen ( RAMAccessEnable === BitPat ( "b010?1" ) ) {
2023-06-29 18:29:54 +08:00
WbEn : = false . B
RxEn : = false . B
TxEn : = true . B // RxEn access stage and r_TxEn is enabled
ram_addr : = Cat ( TxBDAddress , TxPointerRead )
ram_di : = TxBDDataIn ;
2023-06-30 14:46:23 +08:00
} . elsewhen ( RAMAccessEnable === BitPat ( "b001??" ) ) {
2023-06-29 18:29:54 +08:00
WbEn : = true . B // TxEn access stage (we always go to wb access stage)
RxEn : = false . B
TxEn : = false . B
ram_addr : = io . WB_ADR_I //[9:2]
ram_di : = io . WB_DAT_I
BDWrite : = io . BDCs & Fill ( 4 , io . WB_WE_I )
BDRead : = io . BDCs . orR & ~ io . WB_WE_I
2023-06-30 14:46:23 +08:00
} . elsewhen ( RAMAccessEnable === BitPat ( "b10000" ) ) {
2023-06-29 18:29:54 +08:00
WbEn : = false . B // WbEn access stage and there is no need for other stages. WbEn needs to be switched off for a bit
2023-06-30 14:46:23 +08:00
} . elsewhen ( RAMAccessEnable === BitPat ( "b00000" ) ) {
2023-06-29 18:29:54 +08:00
WbEn : = true . B // Idle state. We go to WbEn access stage.
RxEn : = false . B
TxEn : = false . B
ram_addr : = io . WB_ADR_I //[9:2]
ram_di : = io . WB_DAT_I
BDWrite : = io . BDCs & Fill ( 4 , io . WB_WE_I )
BDRead : = io . BDCs . orR & ~ io . WB_WE_I
}
2023-06-28 23:43:03 +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
when ( TxEn & TxEn_q & 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
} . elsewhen ( TxEn_q ) {
TxPointerRead : = false . B
}
// Writing status back to the Tx buffer descriptor
TxStatusWrite : = ( TxDonePacket_NotCleared | TxAbortPacket_NotCleared ) & TxEn & TxEn_q & ~ BlockingTxStatusWrite
2023-06-30 16:00:02 +08:00
// Status writing must occur only once. Meanwhile it is blocked.
when ( ~ TxDone_wb ( 1 ) & ~ TxAbort_wb ( 1 ) ) {
2023-06-28 23:43:03 +08:00
BlockingTxStatusWrite : = false . B
} . elsewhen ( TxStatusWrite ) {
BlockingTxStatusWrite : = true . B
}
2023-06-29 18:29:54 +08:00
val BlockingTxStatusWrite_sync2_txclk = Wire ( Bool ( ) )
val BlockingTxStatusWrite_sync3_txclk = Wire ( Bool ( ) )
io . RstDeferLatched : = BlockingTxStatusWrite_sync2_txclk & ~ BlockingTxStatusWrite_sync3_txclk
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-06-28 23:43:03 +08:00
when ( TxEn & TxEn_q & 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;
when ( TxEn & TxEn_q & TxBDRead ) {
2023-06-29 23:28:05 +08:00
TxLength : = txBuffDesc . len
2023-06-28 23:43:03 +08:00
} . elsewhen ( MasterWbTX & io . m_wb_ack_i ) {
2023-06-30 14:46:23 +08:00
when ( TxLength < 4. U ) {
2023-06-28 23:43:03 +08:00
TxLength : = 0. U
} . elsewhen ( TxPointerLSB_rst === 0. U ) {
TxLength : = TxLength - 4. U // Length is subtracted at the data request
} . elsewhen ( TxPointerLSB_rst === 1. U ) {
TxLength : = TxLength - 3. U // Length is subtracted at the data request
} . elsewhen ( TxPointerLSB_rst === 2. U ) {
TxLength : = TxLength - 2. U // Length is subtracted at the data request
} . elsewhen ( TxPointerLSB_rst === 3. U ) {
TxLength : = TxLength - 1. U // Length is subtracted at the data request
}
}
//Latching length from the buffer descriptor;
when ( TxEn & TxEn_q & TxBDRead ) {
2023-06-29 23:28:05 +08:00
LatchedTxLength : = txBuffDesc . len
2023-06-28 23:43:03 +08:00
}
when ( TxEn & TxEn_q & 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.
TxPointerLSB : = ram_do ( 1 , 0 ) // Latching 2 MSB bits of the buffer descriptor. Since word accesses are performed, valid data does not necesserly start at byte 0 (could be byte 0, 1, 2 or 3). This signals are used for proper selection of the star byte (TxData and TxByteCnt) are set by this two bits.
2023-06-28 23:43:03 +08:00
} . elsewhen ( IncrTxPointer & ~ BlockingIncrementTxPointer ) {
TxPointerMSB : = TxPointerMSB + 1. U // TxPointer is word-aligned
}
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
// Latching 2 MSB bits of the buffer descriptor. After the read access, TxLength needs to be decremented for the number of the valid bytes (1 to 4 bytes are valid in the first word). After the first read all bytes are valid so this two bits are reset to zero.
when ( TxEn & TxEn_q & TxPointerRead ) {
TxPointerLSB_rst : = ram_do ( 1 , 0 )
} . elsewhen ( MasterWbTX & io . m_wb_ack_i ) { // After first access pointer is word alligned
TxPointerLSB_rst : = 0. U
}
when ( MasterAccessFinished ) {
BlockingIncrementTxPointer : = false . B
} . elsewhen ( IncrTxPointer ) {
BlockingIncrementTxPointer : = true . B
}
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-06-30 16:00:02 +08:00
} . elsewhen ( TxEn & TxEn_q & TxPointerRead ) {
2023-06-28 23:43:03 +08:00
ReadTxDataFromMemory : = true . B
}
2023-06-30 16:00:02 +08:00
val tx_burst = ReadTxDataFromMemory & ~ BlockReadTxDataFromMemory & tx_burst_en
2023-06-28 23:43:03 +08:00
when ( ( TxBufferAlmostFull | TxLength <= 4. U ) & MasterWbTX & ( ~ cyc_cleared ) & ( ~ ( TxAbortPacket_NotCleared | TxRetryPacket_NotCleared ) ) ) {
BlockReadTxDataFromMemory : = true . B
} . elsewhen ( ReadTxDataFromFifo_wb | TxDonePacket | TxAbortPacket | TxRetryPacket ) {
BlockReadTxDataFromMemory : = false . B
}
2023-06-29 18:29:54 +08:00
MasterAccessFinished : = io . m_wb_ack_i | io . m_wb_err_i
2023-06-28 23:43:03 +08:00
// Enabling master wishbone access to the memory for two devices TX and RX.
2023-06-30 16:00:02 +08:00
val masterStage = Cat ( MasterWbTX , MasterWbRX , ( ReadTxDataFromMemory & ~ BlockReadTxDataFromMemory ) , WriteRxDataToMemory , MasterAccessFinished , cyc_cleared , tx_burst , rx_burst )
2023-06-28 23:43:03 +08:00
// Switching between two stages depends on enable signals
when (
masterStage === BitPat ( "b00100010" ) | // Idle and MRB needed
masterStage === BitPat ( "b101?101?" ) | // MRB continues
masterStage === BitPat ( "b10100110" ) | // Clear (previously MR) and MRB needed
masterStage === BitPat ( "b011?011?" )
) { // Clear (previously MW) and MRB needed
MasterWbTX : = true . B // tx burst
MasterWbRX : = false . B
m_wb_cyc_o : = true . B
m_wb_we_o : = false . B
m_wb_sel_o : = "hf" . U
cyc_cleared : = false . B
IncrTxPointer : = true . B
tx_burst_cnt : = tx_burst_cnt + 1. U
when ( tx_burst_cnt === 0. U ) {
m_wb_adr_o : = TxPointerMSB
} . otherwise {
2023-06-29 18:29:54 +08:00
m_wb_adr_o : = m_wb_adr_o + 1. U
2023-06-28 23:43:03 +08:00
}
when ( tx_burst_cnt === 3. U ) {
tx_burst_en : = false . B
m_wb_cti_o : = "b111" . U
} . otherwise {
m_wb_cti_o : = "b010" . U
}
} . elsewhen (
masterStage === BitPat ( "b00?100?1" ) | // Idle and MWB needed
masterStage === BitPat ( "b01?110?1" ) | // MWB continues
masterStage === BitPat ( "b01010101" ) | // Clear (previously MW) and MWB needed
masterStage === BitPat ( "b10?101?1" ) // Clear (previously MR) and MWB needed
) {
MasterWbTX : = false . B // rx burst
MasterWbRX : = true . B
m_wb_cyc_o : = true . B
m_wb_we_o : = true . B
m_wb_sel_o : = RxByteSel
IncrTxPointer : = false . B
cyc_cleared : = false . B
rx_burst_cnt : = rx_burst_cnt + 1. U
when ( rx_burst_cnt === 0. U ) {
m_wb_adr_o : = RxPointerMSB
} . otherwise {
m_wb_adr_o : = m_wb_adr_o + 1. U
}
when ( rx_burst_cnt === 3. U ) {
rx_burst_en : = false . B
m_wb_cti_o : = "b111" . U
} . otherwise {
2023-06-29 18:29:54 +08:00
m_wb_cti_o : = "b010" . U
2023-06-28 23:43:03 +08:00
}
} . elsewhen ( masterStage === BitPat ( "b00?100?0" ) ) { // idle and MW is needed (data write to rx buffer)
MasterWbTX : = false . B
MasterWbRX : = true . B
m_wb_adr_o : = RxPointerMSB
m_wb_cyc_o : = true . B
m_wb_we_o : = true . B
m_wb_sel_o : = RxByteSel
IncrTxPointer : = false . B
} . elsewhen ( masterStage === BitPat ( "b00100000" ) ) { // idle and MR is needed (data read from tx buffer)
MasterWbTX : = true . B
MasterWbRX : = false . B
m_wb_adr_o : = TxPointerMSB ;
m_wb_cyc_o : = true . B
m_wb_we_o : = false . B
m_wb_sel_o : = "hf" . U
IncrTxPointer : = true . B
} . elsewhen (
masterStage === BitPat ( "b10100100" ) | // MR and MR is needed (data read from tx buffer)
masterStage === BitPat ( "b011?010?" ) // MW and MR is needed (data read from tx buffer)
) {
MasterWbTX : = true . B
MasterWbRX : = false . B
m_wb_adr_o : = TxPointerMSB ;
m_wb_cyc_o : = true . B
m_wb_we_o : = false . B
m_wb_sel_o : = "hf" . U
cyc_cleared : = false . B
IncrTxPointer : = true . B
} . elsewhen (
masterStage === BitPat ( "b01010100" ) | // MW and MW needed (data write to rx buffer)
masterStage === BitPat ( "b10?101?0" ) // MR and MW is needed (data write to rx buffer)
) {
MasterWbTX : = false . B
MasterWbRX : = true . B
m_wb_adr_o : = RxPointerMSB ;
m_wb_cyc_o : = true . B
m_wb_we_o : = true . B
m_wb_sel_o : = RxByteSel ;
cyc_cleared : = false . B
IncrTxPointer : = false . B
} . elsewhen (
masterStage === BitPat ( "b01011000" ) | // MW and MW needed (cycle is cleared between previous and next access)
masterStage === BitPat ( "b011?10?0" ) | // MW and MW or MR or MRB needed (cycle is cleared between previous and next access)
masterStage === BitPat ( "b10101000" ) | // MR and MR needed (cycle is cleared between previous and next access)
masterStage === BitPat ( "b10?1100?" ) // MR and MR or MW or MWB (cycle is cleared between previous and next access)
) {
m_wb_cyc_o : = false . B // whatever and master read or write is needed. We need to clear m_wb_cyc_o before next access is started
cyc_cleared : = true . B
IncrTxPointer : = false . B
tx_burst_cnt : = 0. U
tx_burst_en : = ( txfifo_cnt < 12. U ) & ( TxLength > 20. U )
rx_burst_cnt : = 0. U
rx_burst_en : = Mux ( MasterWbRX , enough_data_in_rxfifo_for_burst_plus1 , enough_data_in_rxfifo_for_burst ) // Counter is not decremented, yet, so plus1 is used.
m_wb_cti_o : = 0. U
} . elsewhen (
masterStage === BitPat ( "b??001000" ) | // whatever and no master read or write is needed (ack or err comes finishing previous access)
masterStage === BitPat ( "b??000100" ) // Between cyc_cleared request was cleared
) {
MasterWbTX : = false . B
MasterWbRX : = false . B
m_wb_cyc_o : = false . B
cyc_cleared : = false . B
IncrTxPointer : = false . B
rx_burst_cnt : = 0. U
// Counter is not decremented, yet, so plus1 is used.
rx_burst_en : = Mux ( MasterWbRX , enough_data_in_rxfifo_for_burst_plus1 , enough_data_in_rxfifo_for_burst )
m_wb_cti_o : = 0. U
} . elsewhen ( masterStage === BitPat ( "b00000000" ) ) { // whatever and no master read or write is needed (ack or err comes finishing previous access)
tx_burst_cnt : = 0. U
tx_burst_en : = ( txfifo_cnt < 12. U ) & ( TxLength > 20. U )
} . otherwise {
}
TxFifoClear : = ( TxAbortPacket | TxRetryPacket )
2023-06-29 18:29:54 +08:00
val tx_fifo = Module ( new MacFifo ( dw = 32 , dp = 16 ) )
2023-06-28 23:43:03 +08:00
tx_fifo . io . data_in : = io . m_wb_dat_i
tx_fifo . io . write : = MasterWbTX & io . m_wb_ack_i
tx_fifo . io . read : = ReadTxDataFromFifo_wb & ~ TxBufferEmpty
tx_fifo . io . clear : = TxFifoClear
TxData_wb : = tx_fifo . io . data_out
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
} . elsewhen ( TxStartFrm_syncb2 ) {
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 )
val TxValidBytesLatched = RegInit ( 0. U ( 2. W ) )
// val LatchValidBytes = RegNext((TxLength < 4.U) & TxBDReady, false.B)
// val LatchValidBytes_q = RegNext(LatchValidBytes, false.B)
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)
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
when ( io . r_TxEn & ( ~ r_TxEn_q ) ) {
TxBDAddress : = 0. U
} . elsewhen ( TxStatusWrite ) {
TxBDAddress : = TempTxBDAddress
}
// Latching Rx buffer descriptor address
when ( io . r_RxEn & ( ~ r_RxEn_q ) ) {
RxBDAddress : = io . r_TxBDNum ( 6 , 0 )
} . 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 )
val LatchedRxLength_rxclk = Wire ( UInt ( 16. W ) )
val RxStatusInLatched_rxclk = Wire ( UInt ( 9. W ) )
RxBDDataIn : = Cat ( LatchedRxLength_rxclk , 0. U ( 1. W ) , RxStatus , 0. U ( 4. W ) , RxStatusInLatched_rxclk )
2023-06-28 23:43:03 +08:00
TxBDDataIn : = Cat ( LatchedTxLength , 0. U ( 1. W ) , TxStatus , 0. U ( 2. W ) , TxStatusInLatched )
// Signals used for various purposes
2023-06-30 16:00:02 +08:00
TxRetryPulse : = TxRetry_wb ( 1 ) & ~ TxRetry_wb ( 2 )
TxDonePulse : = TxDone_wb ( 1 ) & ~ TxDone_wb ( 2 )
TxAbortPulse : = TxAbort_wb ( 1 ) & ~ TxAbort_wb ( 2 )
2023-06-29 18:29:54 +08:00
2023-06-28 23:43:03 +08:00
val TxAbortPacketBlocked = RegInit ( false . B )
2023-06-30 16:00:02 +08:00
when (
TxAbort_wb ( 1 ) & ( ~ TxAbortPacketBlocked ) & MasterWbTX & ( ~ tx_burst_en ) & MasterAccessFinished |
TxAbort_wb ( 1 ) & ( ~ TxAbortPacketBlocked ) & ( ~ MasterWbTX ) ) {
2023-06-28 23:43:03 +08:00
TxAbortPacket : = true . B
} . otherwise {
TxAbortPacket : = false . B
}
when ( TxEn & TxEn_q & TxAbortPacket_NotCleared ) {
TxAbortPacket_NotCleared : = false . B
2023-06-30 16:00:02 +08:00
} . elsewhen (
TxAbort_wb ( 1 ) & ( ~ TxAbortPacketBlocked ) & MasterWbTX & ( ~ tx_burst_en ) & MasterAccessFinished |
TxAbort_wb ( 1 ) & ( ~ TxAbortPacketBlocked ) & ( ~ MasterWbTX ) ) {
2023-06-28 23:43:03 +08:00
TxAbortPacket_NotCleared : = true . B
}
2023-06-30 16:00:02 +08:00
when ( ~ TxAbort_wb ( 1 ) & TxAbort_wb ( 2 ) ) {
2023-06-28 23:43:03 +08:00
TxAbortPacketBlocked : = false . B
} . elsewhen ( TxAbortPacket ) {
TxAbortPacketBlocked : = true . B
}
val TxRetryPacketBlocked = RegInit ( false . B )
when (
2023-06-30 16:00:02 +08:00
TxRetry_wb ( 1 ) & ~ TxRetryPacketBlocked & MasterWbTX & ~ tx_burst_en & MasterAccessFinished |
TxRetry_wb ( 1 ) & ~ 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-06-30 16:00:02 +08:00
TxRetry_wb ( 1 ) & ~ TxRetryPacketBlocked & MasterWbTX & ~ tx_burst_en & MasterAccessFinished |
TxRetry_wb ( 1 ) & ~ TxRetryPacketBlocked & ~ MasterWbTX ) {
2023-06-28 23:43:03 +08:00
TxRetryPacket_NotCleared : = true . B
}
2023-06-30 16:00:02 +08:00
when ( ~ TxRetry_wb ( 1 ) & TxRetry_wb ( 2 ) ) {
2023-06-28 23:43:03 +08:00
TxRetryPacketBlocked : = false . B
} . elsewhen ( TxRetryPacket ) {
TxRetryPacketBlocked : = true . B
}
val TxDonePacketBlocked = RegInit ( false . B )
when (
2023-06-30 16:00:02 +08:00
TxDone_wb ( 1 ) & ~ tx_burst_en & MasterWbTX & MasterAccessFinished & ~ TxDonePacketBlocked |
TxDone_wb ( 1 ) & ~ MasterWbTX & ~ TxDonePacketBlocked ) {
2023-06-28 23:43:03 +08:00
TxDonePacket : = true . B
} . otherwise {
TxDonePacket : = false . B
}
when ( TxEn & TxEn_q & TxDonePacket_NotCleared ) {
TxDonePacket_NotCleared : = false . B
} . elsewhen (
2023-06-30 16:00:02 +08:00
TxDone_wb ( 1 ) & ~ tx_burst_en & MasterWbTX & MasterAccessFinished & ( ~ TxDonePacketBlocked ) |
TxDone_wb ( 1 ) & ~ MasterWbTX & ( ~ TxDonePacketBlocked ) ) {
2023-06-28 23:43:03 +08:00
TxDonePacket_NotCleared : = true . B
}
2023-06-30 16:00:02 +08:00
when ( ~ TxDone_wb ( 1 ) & TxDone_wb ( 2 ) ) {
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
}
ReadTxDataFromFifo_wb : = ReadTxDataFromFifo_sync2 & ~ ReadTxDataFromFifo_sync3
// End: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I
StartRxBDRead : =
RxStatusWrite |
RxAbortSync3 & ~ RxAbortSync4 |
io . r_RxEn & ~ r_RxEn_q
// Reading the Rx buffer descriptor
when ( StartRxBDRead & ~ RxReady ) {
RxBDRead : = true . B
} . elsewhen ( RxBDReady ) {
RxBDRead : = false . B
}
// Reading of the next receive buffer descriptor starts after reception status
// is written to the previous one.
// Latching READY status of the Rx buffer descriptor
when ( RxPointerRead ) {
RxBDReady : = false . B
} . elsewhen ( RxEn & RxEn_q & RxBDRead ) {
2023-06-29 23:28:05 +08:00
RxBDReady : = rxBuffDesc . e // RxBDReady is sampled only once at the beginning
2023-06-28 23:43:03 +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)
when ( RxEn & RxEn_q & 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
when ( ShiftEnded | RxAbortSync2 & ~ RxAbortSync3 | ~ io . r_RxEn & r_RxEn_q ) {
RxReady : = false . B
} . elsewhen ( RxEn & RxEn_q & RxPointerRead ) {
RxReady : = true . B
}
// Reading Rx BD pointer
StartRxPointerRead : = RxBDRead & RxBDReady
// Reading Tx BD Pointer
when ( StartRxPointerRead ) {
RxPointerRead : = true . B
} . elsewhen ( RxEn & RxEn_q ) {
RxPointerRead : = false . B
}
//Latching Rx buffer pointer from buffer descriptor;
when ( RxEn & RxEn_q & RxPointerRead ) {
RxPointerMSB : = ram_do ( 31 , 2 )
} . elsewhen ( MasterWbRX & io . m_wb_ack_i ) {
RxPointerMSB : = RxPointerMSB + 1. U // Word access (always word access. m_wb_sel_o are used for selecting bytes)
}
//Latching last addresses from buffer descriptor (used as byte-half-word indicator);
when ( MasterWbRX & io . m_wb_ack_i ) { // After first write all RxByteSel are active
RxPointerLSB_rst : = 0. U
} . elsewhen ( RxEn & RxEn_q & RxPointerRead ) {
RxPointerLSB_rst : = ram_do ( 1 , 0 )
}
RxByteSel : = Mux1H ( Seq (
( RxPointerLSB_rst === 0. U ) -> "hf" . U ,
( RxPointerLSB_rst === 1. U ) -> "h7" . U ,
( RxPointerLSB_rst === 2. U ) -> "h3" . U ,
( RxPointerLSB_rst === 3. U ) -> "h1" . U ,
) )
when ( ~ RxReady & io . r_RxEn & WbEn & ~ WbEn_q ) {
RxEn_needed : = true . B
} . elsewhen ( RxPointerRead & RxEn & RxEn_q ) {
RxEn_needed : = false . B
}
// Reception status is written back to the buffer descriptor after the end of frame is detected.
2023-06-29 18:29:54 +08:00
RxStatusWrite : = ShiftEnded & RxEn & RxEn_q
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
val LastByteIn_rxclk = Wire ( Bool ( ) )
val RxByteCnt_rxclk = Wire ( UInt ( 2. W ) )
val RxEnableWindow_rxclk = Wire ( Bool ( ) )
StartShiftWillEnd : = LastByteIn_rxclk | io . RxValid & io . RxEndFrm & RxByteCnt_rxclk . andR & RxEnableWindow_rxclk
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
// Indicating start of the reception process
val ShiftWillEnd_rxclk = Wire ( Bool ( ) )
SetWriteRxDataToFifo : =
( io . RxValid & RxReady & ~ io . RxStartFrm & RxEnableWindow_rxclk & ( RxByteCnt_rxclk . andR ) ) |
( io . RxValid & RxReady & io . RxStartFrm & ( RxPointerLSB_rst . andR ) ) |
( ShiftWillEnd_rxclk & LastByteIn_rxclk & ( RxByteCnt_rxclk . andR ) )
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
WriteRxDataToFifo_wb : = WriteRxDataToFifoSync2 & ~ WriteRxDataToFifoSync3
RxFifoReset : = SyncRxStartFrm_q & ~ SyncRxStartFrm_q2
val rx_fifo = Module ( new MacFifo ( dw = 32 , dp = 16 ) )
val RxDataLatched2_rxclk = Wire ( UInt ( 32. W ) )
rx_fifo . io . data_in : = RxDataLatched2_rxclk
rx_fifo . io . write : = WriteRxDataToFifo_wb & ~ RxBufferFull
rx_fifo . io . read : = MasterWbRX & io . m_wb_ack_i
rx_fifo . io . clear : = RxFifoReset
io . m_wb_dat_o : = rx_fifo . io . data_out
RxBufferFull : = rx_fifo . io . full
RxBufferAlmostEmpty : = rx_fifo . io . almost_empty
RxBufferEmpty : = rx_fifo . io . empty
rxfifo_cnt : = rx_fifo . io . cnt
enough_data_in_rxfifo_for_burst : = rxfifo_cnt >= 4. U
enough_data_in_rxfifo_for_burst_plus1 : = rxfifo_cnt > 4. U
WriteRxDataToMemory : = ~ RxBufferEmpty
rx_burst : = rx_burst_en & WriteRxDataToMemory
when ( ShiftEndedSync1 & ~ ShiftEndedSync2 ) {
ShiftEndedSync3 : = true . B
} . elsewhen ( ShiftEnded ) {
ShiftEndedSync3 : = false . B
}
// Generation of the end-of-frame signal
when ( ShiftEndedSync3 & MasterWbRX & io . m_wb_ack_i & RxBufferAlmostEmpty & ~ ShiftEnded ) {
ShiftEnded : = true . B
} . elsewhen ( RxStatusWrite ) {
ShiftEnded : = false . B
}
RxStatusIn : = Cat ( io . ReceivedPauseFrm , io . AddressMiss , RxOverrun , io . InvalidSymbol , io . DribbleNibble , io . ReceivedPacketTooBig , io . ShortFrame , io . LatchedCrcError , io . RxLateCollision )
// Rx overrun
when ( RxStatusWrite ) {
RxOverrun : = false . B
} . elsewhen ( RxBufferFull & WriteRxDataToFifo_wb ) {
RxOverrun : = true . B
}
TxError : = io . TxUnderRun | io . RetryLimit | io . LateCollLatched | io . CarrierSenseLost
// 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
RxError : = ( RxStatusInLatched_rxclk ( 6 , 3 ) . orR ) | ( RxStatusInLatched_rxclk ( 1 , 0 ) . orR )
// Latching and synchronizing RxStatusWrite signal. This signal is used for clearing the ReceivedPauseFrm signal
when ( RxStatusWriteLatched_syncb2 ) {
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
when ( RxStatusWrite & RxIRQEn & io . ReceivedPacketGood & ( ~ io . ReceivedPauseFrm | io . ReceivedPauseFrm & io . r_PassAll & ( ~ io . r_RxFlow ) ) ) {
RxB_IRQ : = ( ~ RxError )
} . otherwise {
RxB_IRQ : = false . B
}
// Rx Error Interrupt
when ( RxStatusWrite & RxIRQEn & ( ~ io . ReceivedPauseFrm | io . ReceivedPauseFrm & io . r_PassAll & ( ~ io . r_RxFlow ) ) ) {
RxE_IRQ : = RxError
} . otherwise {
RxE_IRQ : = false . B
}
// Busy Interrupt
val Busy_IRQ_rck_rxclk = Wire ( Bool ( ) )
val Busy_IRQ_sync1 = RegNext ( Busy_IRQ_rck_rxclk )
val Busy_IRQ_sync2 = RegNext ( Busy_IRQ_sync1 )
val Busy_IRQ_sync3 = RegNext ( Busy_IRQ_sync2 )
2023-06-29 21:14:51 +08:00
val Busy_IRQ_syncb1 = RegNext ( Busy_IRQ_sync2 , false . B )
val Busy_IRQ_syncb2 = RegNext ( Busy_IRQ_syncb1 , false . B )
2023-06-29 18:29:54 +08:00
io . Busy_IRQ : = Busy_IRQ_sync2 & ~ Busy_IRQ_sync3
}
trait MacTileLinkTXClk { this : MacTileLinkBase =>
withClockAndReset ( io . MTxClk . asClock , reset ) {
2023-06-29 21:14:51 +08:00
val Flop = RegInit ( false . B )
// Synchronizing BlockingTxStatusWrite to MTxClk
val BlockingTxStatusWrite_sync1 = RegNext ( BlockingTxStatusWrite , false . B )
val BlockingTxStatusWrite_sync2 = RegNext ( BlockingTxStatusWrite_sync1 , false . B ) ; BlockingTxStatusWrite_sync2_txclk : = BlockingTxStatusWrite_sync2
val BlockingTxStatusWrite_sync3 = RegNext ( BlockingTxStatusWrite_sync2 , false . B ) ; BlockingTxStatusWrite_sync3_txclk : = BlockingTxStatusWrite_sync3
// Synchronizing TxStartFrm_wb to MTxClk
val TxStartFrm_sync1 = RegNext ( TxStartFrm_wb , false . B )
val TxStartFrm_sync2 = RegNext ( TxStartFrm_sync1 , false . B ) ; TxStartFrm_sync2_txclk : = TxStartFrm_sync2
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_syncb1 = RegNext ( ReadTxDataFromFifo_sync2 , false . B )
val ReadTxDataFromFifo_syncb2 = RegNext ( ReadTxDataFromFifo_syncb1 , false . B )
val ReadTxDataFromFifo_syncb3 = RegNext ( ReadTxDataFromFifo_syncb2 , false . B )
2023-06-29 18:29:54 +08:00
// Changes for tx occur every second clock. Flop is used for this manner.
2023-06-29 21:14:51 +08:00
when ( io . TxDone | io . TxAbort | TxRetry_q ) {
2023-06-29 18:29:54 +08:00
Flop : = false . B
} . elsewhen ( io . TxUsedData ) {
Flop : = ~ Flop
}
2023-06-29 21:14:51 +08:00
when ( TxStartFrm_sync2 ) {
2023-06-29 18:29:54 +08:00
TxStartFrm : = true . B
} . elsewhen ( TxUsedData_q | ~ TxStartFrm_sync2 & ( io . TxRetry & ( ~ TxRetry_q ) | io . TxAbort & ( ~ TxAbort_q ) ) ) {
TxStartFrm : = false . B
}
// Indication of the last word
2023-06-29 21:14:51 +08:00
when ( ( TxEndFrm | io . TxAbort | io . TxRetry ) & Flop ) {
2023-06-29 18:29:54 +08:00
LastWord : = false . B
} . elsewhen ( io . TxUsedData & Flop & TxByteCnt === 3. U ) {
LastWord : = TxEndFrm_wb
}
// Tx end frame generation
2023-06-29 21:14:51 +08:00
when ( Flop & TxEndFrm | io . TxAbort | TxRetry_q ) {
2023-06-29 18:29:54 +08:00
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)
2023-06-29 21:14:51 +08:00
when ( TxStartFrm_sync2 & ~ TxStartFrm ) {
2023-06-29 18:29:54 +08:00
TxData : = Mux1H ( Seq (
( TxPointerLSB === 0. U ) -> TxData_wb ( 31 , 24 ) , // Big Endian Byte Ordering
( TxPointerLSB === 1. U ) -> TxData_wb ( 23 , 16 ) , // Big Endian Byte Ordering
( TxPointerLSB === 2. U ) -> TxData_wb ( 15 , 8 ) , // Big Endian Byte Ordering
( TxPointerLSB === 3. U ) -> TxData_wb ( 7 , 0 ) , // Big Endian Byte Ordering
) )
} . elsewhen ( TxStartFrm & io . TxUsedData & TxPointerLSB === 3. U ) {
TxData : = TxData_wb ( 31 , 24 ) // Big Endian Byte Ordering
} . elsewhen ( io . TxUsedData & Flop ) {
TxData : = Mux1H ( Seq (
( TxByteCnt === 0. U ) -> TxDataLatched ( 31 , 24 ) , // Big Endian Byte Ordering
( TxByteCnt === 1. U ) -> TxDataLatched ( 23 , 16 ) ,
( TxByteCnt === 2. U ) -> TxDataLatched ( 15 , 8 ) ,
( TxByteCnt === 3. U ) -> TxDataLatched ( 7 , 0 ) ,
) )
}
// Latching tx data
2023-06-29 21:14:51 +08:00
when (
2023-06-29 18:29:54 +08:00
TxStartFrm_sync2 & ~ TxStartFrm |
io . TxUsedData & Flop & TxByteCnt === 3. U |
TxStartFrm & io . TxUsedData & Flop & TxByteCnt === 0. U ) {
TxDataLatched : = TxData_wb
}
2023-06-29 21:14:51 +08:00
val TxUnderRun_sync1 = RegInit ( false . B )
2023-06-29 18:29:54 +08:00
// Tx under run
2023-06-29 21:14:51 +08:00
when ( TxUnderRun_wb ) {
2023-06-29 18:29:54 +08:00
TxUnderRun_sync1 : = true . B
} . elsewhen ( BlockingTxStatusWrite_sync2 ) {
TxUnderRun_sync1 : = false . B
}
// Tx under run
2023-06-29 21:14:51 +08:00
when ( BlockingTxStatusWrite_sync2 ) {
2023-06-29 18:29:54 +08:00
TxUnderRun : = false . B
} . elsewhen ( TxUnderRun_sync1 ) {
TxUnderRun : = true . B
}
// Tx Byte counter
2023-06-29 21:14:51 +08:00
when ( TxAbort_q | TxRetry_q ) {
2023-06-29 18:29:54 +08:00
TxByteCnt : = 0. U
} . elsewhen ( TxStartFrm & ~ io . TxUsedData ) {
TxByteCnt : = Mux1H ( Seq (
( TxPointerLSB === 0. U ) -> 1. U ,
( TxPointerLSB === 1. U ) -> 2. U ,
( TxPointerLSB === 2. U ) -> 3. U ,
( TxPointerLSB === 3. U ) -> 0. U ,
) )
} . elsewhen ( io . TxUsedData & Flop ) {
TxByteCnt : = TxByteCnt + 1. U
}
2023-06-29 21:14:51 +08:00
when ( TxStartFrm_sync2 & ~ TxStartFrm | io . TxUsedData & Flop & TxByteCnt === 3. U &
2023-06-29 18:29:54 +08:00
~ LastWord | TxStartFrm & io . TxUsedData & Flop & TxByteCnt === 0. U ) {
ReadTxDataFromFifo_tck : = true . B
} . elsewhen ( ReadTxDataFromFifo_syncb2 & ~ ReadTxDataFromFifo_syncb3 ) {
ReadTxDataFromFifo_tck : = false . B
}
}
}
trait MacTileLinkRXClk { this : MacTileLinkBase =>
withClockAndReset ( io . MRxClk . asClock , reset ) {
2023-06-29 21:14:51 +08:00
val RxDataLatched2 = RegInit ( 0. U ( 32. W ) ) ; RxDataLatched2_rxclk : = RxDataLatched2
val RxDataLatched1 = RegInit ( 0. U ( 24. W ) ) // Big Endian Byte Ordering[31:8]
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 LatchedRxLength = RegInit ( 0. U ( 16. W ) ) ; LatchedRxLength_rxclk : = LatchedRxLength
val RxAbortLatched = RegInit ( false . B ) ; RxAbortLatched_rxclk : = RxAbortLatched
val RxStatusInLatched = RegInit ( 0. U ( 9. W ) ) ; RxStatusInLatched_rxclk : = RxStatusInLatched
val ShiftEnded_rck = RegInit ( false . B ) ; ShiftEnded_rck_txclk : = ShiftEnded_rck
val ShiftEndedSync_c1 = RegNext ( ShiftEndedSync2 , false . B )
val ShiftEndedSync_c2 = RegNext ( ShiftEndedSync_c1 , false . B )
val RxAbortSyncb1 = RegNext ( RxAbortSync2 , false . B )
val RxAbortSyncb2 = RegNext ( RxAbortSyncb1 , false . B )
val RxEnableWindow = RegInit ( false . B ) ; RxEnableWindow_rxclk : = RxEnableWindow
val LatchedRxStartFrm = RegInit ( false . B ) ; LatchedRxStartFrm_rxclk : = LatchedRxStartFrm
val RxStatusWriteLatched_sync1 = RegNext ( RxStatusWriteLatched , false . B )
val RxStatusWriteLatched_sync2 = RegNext ( RxStatusWriteLatched_sync1 , false . B ) ; io . RxStatusWriteLatched_sync2 : = RxStatusWriteLatched_sync2
2023-06-29 18:29:54 +08:00
// Indicating that last byte is being reveived
2023-06-29 21:14:51 +08:00
when ( ShiftWillEnd & RxByteCnt . andR | io . RxAbort ) {
2023-06-29 18:29:54 +08:00
LastByteIn : = false . B
} . elsewhen ( io . RxValid & RxReady & io . RxEndFrm & ~ ( RxByteCnt . andR ) & RxEnableWindow ) {
LastByteIn : = true . B
}
// Indicating that data reception will end
2023-06-29 21:14:51 +08:00
when ( ShiftEnded_rck | io . RxAbort ) {
2023-06-29 18:29:54 +08:00
ShiftWillEnd : = false . B
} . elsewhen ( StartShiftWillEnd ) {
ShiftWillEnd : = true . B
}
// Receive byte counter
2023-06-29 21:14:51 +08:00
when ( ShiftEnded_rck | io . RxAbort ) {
2023-06-29 18:29:54 +08:00
RxByteCnt : = 0. U
} . elsewhen ( io . RxValid & io . RxStartFrm & RxReady ) {
RxByteCnt : = Mux1H ( Seq (
( RxPointerLSB_rst === 0. U ) -> 1. U ,
( RxPointerLSB_rst === 1. U ) -> 2. U ,
( RxPointerLSB_rst === 2. U ) -> 3. U ,
( RxPointerLSB_rst === 3. U ) -> 0. U ,
) )
} . elsewhen ( io . RxValid & RxEnableWindow & RxReady | LastByteIn ) {
RxByteCnt : = RxByteCnt + 1. U
}
// Indicates how many bytes are valid within the last word
2023-06-29 21:14:51 +08:00
when ( io . RxValid & io . RxStartFrm ) {
2023-06-28 23:43:03 +08:00
RxValidBytes : = Mux1H ( Seq (
( RxPointerLSB_rst === 0. U ) -> 1. U ,
( RxPointerLSB_rst === 1. U ) -> 2. U ,
( RxPointerLSB_rst === 2. U ) -> 3. U ,
( RxPointerLSB_rst === 3. U ) -> 0. U ,
) )
2023-06-29 18:29:54 +08:00
} . elsewhen ( io . RxValid & ~ LastByteIn & ~ io . RxStartFrm & RxEnableWindow ) {
2023-06-28 23:43:03 +08:00
RxValidBytes : = RxValidBytes + 1. U
}
2023-06-29 21:14:51 +08:00
when ( io . RxValid & RxReady & ~ LastByteIn ) {
2023-06-29 18:29:54 +08:00
when ( io . RxStartFrm ) {
2023-06-28 23:43:03 +08:00
RxDataLatched1 : = Mux1H ( Seq (
( RxPointerLSB_rst === 0. U ) -> Cat ( io . RxData , RxDataLatched1 ( 15 , 0 ) ) , // Big Endian Byte Ordering
( RxPointerLSB_rst === 1. U ) -> Cat ( RxDataLatched1 ( 23 , 16 ) , io . RxData , RxDataLatched1 ( 7 , 0 ) ) ,
( RxPointerLSB_rst === 2. U ) -> Cat ( RxDataLatched1 ( 23 , 8 ) , io . RxData ) ,
( RxPointerLSB_rst === 3. U ) -> RxDataLatched1 ,
) )
} . elsewhen ( RxEnableWindow ) {
2023-06-29 18:29:54 +08:00
RxDataLatched1 : = Mux1H ( Seq (
2023-06-28 23:43:03 +08:00
( RxByteCnt === 0. U ) -> Cat ( io . RxData , RxDataLatched1 ( 15 , 0 ) ) , // Big Endian Byte Ordering
( RxByteCnt === 1. U ) -> Cat ( RxDataLatched1 ( 23 , 16 ) , io . RxData , RxDataLatched1 ( 7 , 0 ) ) ,
( RxByteCnt === 2. U ) -> Cat ( RxDataLatched1 ( 23 , 8 ) , io . RxData ) ,
( RxByteCnt === 3. U ) -> RxDataLatched1 ,
) )
}
}
// Assembling data that will be written to the rx_fifo
2023-06-29 21:14:51 +08:00
when ( SetWriteRxDataToFifo & ~ ShiftWillEnd ) {
2023-06-29 18:29:54 +08:00
RxDataLatched2 : = Cat ( RxDataLatched1 , io . RxData ) // Big Endian Byte Ordering
2023-06-28 23:43:03 +08:00
} . elsewhen ( SetWriteRxDataToFifo & ShiftWillEnd ) {
RxDataLatched2 : = Mux1H ( Seq (
2023-06-29 18:29:54 +08:00
( RxValidBytes === 0. U ) -> Cat ( RxDataLatched1 , io . RxData ) ,
2023-06-28 23:43:03 +08:00
( RxValidBytes === 1. U ) -> Cat ( RxDataLatched1 ( 23 , 16 ) , 0. U ( 24. W ) ) ,
( RxValidBytes === 2. U ) -> Cat ( RxDataLatched1 ( 23 , 8 ) , 0. U ( 16. W ) ) ,
( RxValidBytes === 3. U ) -> Cat ( RxDataLatched1 , 0. U ( 8. W ) ) ,
) )
}
2023-06-29 21:14:51 +08:00
when ( SetWriteRxDataToFifo & ~ io . RxAbort ) {
2023-06-28 23:43:03 +08:00
WriteRxDataToFifo : = true . B
2023-06-29 18:29:54 +08:00
} . elsewhen ( WriteRxDataToFifoSync2 | io . RxAbort ) {
2023-06-28 23:43:03 +08:00
WriteRxDataToFifo : = false . B
}
2023-06-29 21:14:51 +08:00
when ( io . RxStartFrm & ~ SyncRxStartFrm_q ) {
2023-06-28 23:43:03 +08:00
LatchedRxStartFrm : = true . B
} . elsewhen ( SyncRxStartFrm_q ) {
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-06-29 18:29:54 +08:00
} . elsewhen ( io . RxAbort | ShiftEndedSync_c1 & ShiftEndedSync_c2 ) {
2023-06-28 23:43:03 +08:00
ShiftEnded_rck : = false . B
}
// 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-06-29 21:14:51 +08:00
when ( RxAbortSyncb2 ) {
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-06-29 21:14:51 +08:00
when ( io . LoadRxStatus ) {
2023-06-28 23:43:03 +08:00
LatchedRxLength : = io . RxLength
}
2023-06-29 21:14:51 +08:00
when ( io . LoadRxStatus ) {
2023-06-28 23:43:03 +08:00
RxStatusInLatched : = RxStatusIn
}
2023-06-29 21:14:51 +08:00
val Busy_IRQ_rck = RegInit ( false . B ) ; Busy_IRQ_rck_rxclk : = Busy_IRQ_rck
2023-06-28 23:43:03 +08:00
2023-06-29 21:14:51 +08:00
when ( io . RxValid & io . RxStartFrm & ~ RxReady ) {
2023-06-28 23:43:03 +08:00
Busy_IRQ_rck : = true . B
} . elsewhen ( Busy_IRQ_syncb2 ) {
Busy_IRQ_rck : = false . B
}
when ( true . B ) {
Busy_IRQ_syncb1 : = Busy_IRQ_sync2
Busy_IRQ_syncb2 : = Busy_IRQ_syncb1
}
}
}
2023-06-29 18:29:54 +08:00
class MacTileLink extends MacTileLinkBase with MacTileLinkTXClk with MacTileLinkRXClk
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
// trait MacTileLinkSlave{ this: MacTileLinkBase =>
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
// val a = Flipped(new DecoupledIO(new TLBundleA(edge.bundle)))
// val d = new DecoupledIO(new TLBundleD(edge.bundle))
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
// val tlSlvDValid = RegInit(false.B); io.d.valid := tlSlvDValid
2023-06-28 23:43:03 +08:00
2023-06-29 18:29:54 +08:00
// }
2023-06-28 23:43:03 +08:00