2023-10-08 15:37:54 +08:00
|
|
|
package MAC
|
|
|
|
|
|
|
|
|
|
import chisel3._
|
|
|
|
|
import chisel3.util._
|
|
|
|
|
|
|
|
|
|
|
2023-10-24 14:00:51 +08:00
|
|
|
class TxFifo_Stream_Bundle extends Bundle{
|
|
|
|
|
val data = UInt(8.W)
|
|
|
|
|
val isStart = Bool()
|
2023-10-24 16:27:30 +08:00
|
|
|
val isLast = Bool()
|
2023-10-24 14:00:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-10-08 15:37:54 +08:00
|
|
|
class MacTileLinkTxIO extends Bundle{
|
2023-10-23 23:36:01 +08:00
|
|
|
|
2023-10-24 14:00:51 +08:00
|
|
|
val txReq = Flipped(Decoupled(new TxFifo_Stream_Bundle))
|
2023-10-23 23:36:01 +08:00
|
|
|
// val txResp = Decoupled()
|
|
|
|
|
|
|
|
|
|
|
2023-10-08 15:37:54 +08:00
|
|
|
val RstDeferLatched = Output(Bool())
|
|
|
|
|
val BlockingTxStatusWrite_sync = Input(Bool())
|
|
|
|
|
|
|
|
|
|
val TxStartFrm = Output(Bool()) // Transmit packet start frame
|
|
|
|
|
val TxEndFrm = Output(Bool()) // Transmit packet end frame
|
|
|
|
|
val TxData = Output(UInt(8.W)) // Transmit packet data byte
|
|
|
|
|
|
|
|
|
|
val TxUsedData = Input(Bool()) // Transmit packet used data
|
|
|
|
|
val TxRetry = Input(Bool()) // Transmit packet retry
|
|
|
|
|
val TxAbort = Input(Bool()) // Transmit packet abort
|
|
|
|
|
val TxDone = Input(Bool()) // Transmission ended
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MacTileLinkTx extends Module with RequireAsyncReset{
|
|
|
|
|
val io = IO(new MacTileLinkTxIO)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
io.RstDeferLatched := io.BlockingTxStatusWrite_sync & ~RegNext(io.BlockingTxStatusWrite_sync, false.B)
|
|
|
|
|
|
|
|
|
|
val TxStartFrm = RegInit(false.B); io.TxStartFrm := TxStartFrm
|
|
|
|
|
val TxEndFrm = RegInit(false.B); io.TxEndFrm := TxEndFrm
|
|
|
|
|
val TxData = RegInit(0.U(8.W)); io.TxData := TxData
|
|
|
|
|
val LastWord = RegInit(false.B)
|
2023-10-23 23:36:01 +08:00
|
|
|
val ReadTxDataFromFifo_tck = RegInit(false.B);
|
2023-10-08 15:37:54 +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)
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-24 14:00:51 +08:00
|
|
|
when( io.txReq.valid & io.txReq.bits.isStart ){
|
2023-10-08 15:37:54 +08:00
|
|
|
TxStartFrm := true.B
|
2023-10-24 14:00:51 +08:00
|
|
|
} .elsewhen(TxUsedData_q | io.TxRetry & (~TxRetry_q) | io.TxAbort & (~TxAbort_q) ){
|
2023-10-08 15:37:54 +08:00
|
|
|
TxStartFrm := false.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Indication of the last word
|
|
|
|
|
when( (TxEndFrm | io.TxAbort | io.TxRetry) & Flop ){
|
|
|
|
|
LastWord := false.B
|
2023-10-24 16:27:30 +08:00
|
|
|
} .elsewhen( io.txReq.fire ){
|
|
|
|
|
LastWord := io.txReq.bits.isLast
|
2023-10-08 15:37:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tx end frame generation
|
|
|
|
|
when(Flop & TxEndFrm | io.TxAbort | TxRetry_q){
|
|
|
|
|
TxEndFrm := false.B
|
|
|
|
|
} .elsewhen(Flop & LastWord){
|
2023-10-21 21:08:40 +08:00
|
|
|
TxEndFrm := true.B
|
2023-10-08 15:37:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-23 23:36:01 +08:00
|
|
|
io.txReq.ready :=
|
2023-10-24 14:00:51 +08:00
|
|
|
io.txReq.valid & io.txReq.bits.isStart & ~TxStartFrm |
|
|
|
|
|
io.TxUsedData & Flop & ~LastWord |
|
|
|
|
|
TxStartFrm & io.TxUsedData & Flop
|
|
|
|
|
|
2023-10-24 16:27:30 +08:00
|
|
|
when( io.txReq.fire ){
|
|
|
|
|
TxData := io.txReq.bits.data
|
|
|
|
|
}
|
2023-10-23 23:36:01 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( ~(io.txReq.ready & ~io.txReq.valid) )
|
2023-10-08 15:37:54 +08:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|